diff --git a/src/main/java/clap/server/adapter/inbound/web/dto/task/request/FilterTeamStatusRequest.java b/src/main/java/clap/server/adapter/inbound/web/dto/task/request/FilterTeamStatusRequest.java index 6202642e..1ce4e159 100644 --- a/src/main/java/clap/server/adapter/inbound/web/dto/task/request/FilterTeamStatusRequest.java +++ b/src/main/java/clap/server/adapter/inbound/web/dto/task/request/FilterTeamStatusRequest.java @@ -1,13 +1,12 @@ package clap.server.adapter.inbound.web.dto.task.request; import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotNull; import java.util.List; public record FilterTeamStatusRequest( @Schema(description = "정렬 기준 (기여도순, 기본)", example = "기여도순") - String sortBy, + SortBy sortBy, // Enum 타입으로 수정 @Schema(description = "1차 카테고리 ID 목록", example = "[10, 20, 30]") List mainCategoryIds, @@ -19,10 +18,11 @@ public record FilterTeamStatusRequest( String taskTitle ) { public FilterTeamStatusRequest { - sortBy = (sortBy == null || sortBy.isEmpty()) ? "기본" : sortBy; + // 기본값 설정 + sortBy = (sortBy == null) ? SortBy.DEFAULT : sortBy; // 기본값을 DEFAULT로 설정 mainCategoryIds = mainCategoryIds == null ? List.of() : mainCategoryIds; categoryIds = categoryIds == null ? List.of() : categoryIds; taskTitle = taskTitle == null ? "" : taskTitle; } - } + diff --git a/src/main/java/clap/server/adapter/inbound/web/dto/task/request/SortBy.java b/src/main/java/clap/server/adapter/inbound/web/dto/task/request/SortBy.java new file mode 100644 index 00000000..eccc2231 --- /dev/null +++ b/src/main/java/clap/server/adapter/inbound/web/dto/task/request/SortBy.java @@ -0,0 +1,17 @@ +package clap.server.adapter.inbound.web.dto.task.request; + +public enum SortBy { + DEFAULT("기본순"), + CONTRIBUTE("기여도순"); + + private final String value; + + SortBy(String value) { + this.value = value; + } + + public String getValue() { + return value; + } +} + diff --git a/src/main/java/clap/server/adapter/outbound/persistense/repository/task/TaskCustomRepositoryImpl.java b/src/main/java/clap/server/adapter/outbound/persistense/repository/task/TaskCustomRepositoryImpl.java index b14c3079..abc2daff 100644 --- a/src/main/java/clap/server/adapter/outbound/persistense/repository/task/TaskCustomRepositoryImpl.java +++ b/src/main/java/clap/server/adapter/outbound/persistense/repository/task/TaskCustomRepositoryImpl.java @@ -3,8 +3,9 @@ import clap.server.adapter.inbound.web.dto.task.request.FilterTaskBoardRequest; import clap.server.adapter.inbound.web.dto.task.request.FilterTaskListRequest; import clap.server.adapter.inbound.web.dto.task.request.FilterTeamStatusRequest; -import clap.server.adapter.inbound.web.dto.task.response.TeamTaskResponse; +import clap.server.adapter.inbound.web.dto.task.request.SortBy; import clap.server.adapter.inbound.web.dto.task.response.TeamTaskItemResponse; +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 com.querydsl.core.BooleanBuilder; @@ -19,9 +20,9 @@ import org.springframework.stereotype.Repository; import java.time.LocalDateTime; +import java.util.LinkedHashMap; import java.util.List; import java.util.stream.Collectors; -import java.util.Optional; import static clap.server.adapter.outbound.persistense.entity.task.QTaskEntity.taskEntity; import static com.querydsl.core.types.Order.ASC; @@ -87,14 +88,22 @@ public List findTeamStatus(Long memberId, FilterTeamStatusRequ } // 정렬 조건 적용 - OrderSpecifier orderBy = "기여도순".equals(filter != null ? filter.sortBy() : "") - ? new CaseBuilder() - .when(taskEntity.taskStatus.eq(TaskStatus.IN_PROGRESS) - .or(taskEntity.taskStatus.eq(TaskStatus.IN_REVIEWING))) - .then(1) - .otherwise(0) - .desc() - : taskEntity.processor.nickname.asc(); + SortBy sortBy = (filter != null && filter.sortBy() != null) ? filter.sortBy() : SortBy.DEFAULT; + + assert filter != null; + OrderSpecifier orderBy; + if (sortBy == SortBy.CONTRIBUTE) { + // 기여도순 (진행 중 + 검토 중 작업 개수 합 기준 내림차순) + orderBy = new CaseBuilder() + .when(taskEntity.taskStatus.eq(TaskStatus.IN_PROGRESS) + .or(taskEntity.taskStatus.eq(TaskStatus.IN_REVIEWING))) + .then(1) + .otherwise(0) + .desc(); + } else { + // 기본순 (닉네임 오름차순) + orderBy = taskEntity.processor.nickname.asc(); + } // 쿼리 실행 List taskEntities = queryFactory @@ -109,7 +118,7 @@ public List findTeamStatus(Long memberId, FilterTeamStatusRequ } return taskEntities.stream() - .collect(Collectors.groupingBy(t -> t.getProcessor().getMemberId())) + .collect(Collectors.groupingBy(t -> t.getProcessor().getMemberId(), LinkedHashMap::new, Collectors.toList())) .entrySet().stream() .map(entry -> { List taskResponses = entry.getValue().stream() diff --git a/src/main/java/clap/server/application/service/task/TeamStatusService.java b/src/main/java/clap/server/application/service/task/TeamStatusService.java index 28c2b4d2..2bc9b055 100644 --- a/src/main/java/clap/server/application/service/task/TeamStatusService.java +++ b/src/main/java/clap/server/application/service/task/TeamStatusService.java @@ -11,6 +11,8 @@ import java.util.List; +import static clap.server.adapter.inbound.web.dto.task.request.SortBy.CONTRIBUTE; + @ApplicationService public class TeamStatusService implements LoadTeamStatusUsecase, FilterTeamStatusUsecase { @@ -41,6 +43,7 @@ public TeamStatusResponse filterTeamStatus(FilterTeamStatusRequest filter) { // 전체 팀의 진행 중 & 검토 중 작업 수 계산 int totalInProgressTaskCount = members.stream().mapToInt(TeamTaskResponse::inProgressTaskCount).sum(); int totalInReviewingTaskCount = members.stream().mapToInt(TeamTaskResponse::inReviewingTaskCount).sum(); + if (filter.sortBy().equals(CONTRIBUTE)) members.sort((a, b) -> b.totalTaskCount() - a.totalTaskCount()); return new TeamStatusResponse(members, totalInProgressTaskCount, totalInReviewingTaskCount); } diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index c9efe054..d8331c82 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -60,4 +60,4 @@ logging: spring.config.activate.on-profile: prod logging: level: - root: INFO \ No newline at end of file + root: INFO