diff --git a/src/main/java/com/kamco/cd/kamcoback/label/LabelAllocateApiController.java b/src/main/java/com/kamco/cd/kamcoback/label/LabelAllocateApiController.java index 3f2133f7..1395f42b 100644 --- a/src/main/java/com/kamco/cd/kamcoback/label/LabelAllocateApiController.java +++ b/src/main/java/com/kamco/cd/kamcoback/label/LabelAllocateApiController.java @@ -63,7 +63,7 @@ public class LabelAllocateApiController { }) @GetMapping("/admin/workers") public ApiResponseDto getWorkerStatistics( - @Parameter(description = "분석 ID (필수)", required = true, example = "3") @RequestParam + @Parameter(description = "분석 ID (선택)", example = "3") @RequestParam(required = false) Long analUid, @Parameter( description = "작업자 유형 (선택) - 미입력 시 LABELER로 조회", @@ -74,11 +74,9 @@ public class LabelAllocateApiController { defaultValue = "LABELER")) @RequestParam(required = false) String type, - @Parameter(description = "작업자 이름 검색 (부분 일치)", example = "김라벨") @RequestParam(required = false) - String searchName, - @Parameter(description = "작업자 사번 검색 (부분 일치)", example = "1234567") + @Parameter(description = "검색어 (작업자 이름 또는 사번으로 검색, 부분 일치)", example = "김라벨") @RequestParam(required = false) - String searchEmployeeNo, + String search, @Parameter( description = "정렬 조건 (선택) - 미입력 시 이름 오름차순", example = "REMAINING_DESC", @@ -92,14 +90,20 @@ public class LabelAllocateApiController { }, defaultValue = "NAME_ASC")) @RequestParam(required = false) - String sort) { + String sort, + @Parameter(description = "페이지 번호 (0부터 시작)", example = "0") + @RequestParam(defaultValue = "0") + Integer page, + @Parameter(description = "페이지 크기", example = "20") + @RequestParam(defaultValue = "20") + Integer size) { // type이 null이면 기본값으로 LABELER 설정 String workerType = (type == null || type.isEmpty()) ? RoleType.LABELER.name() : type; return ApiResponseDto.ok( labelAllocateService.getWorkerStatistics( - analUid, workerType, searchName, searchEmployeeNo, sort)); + analUid, workerType, search, sort, page, size)); } @Operation(summary = "라벨링작업 관리 > 작업 배정", description = "라벨링작업 관리 > 작업 배정") diff --git a/src/main/java/com/kamco/cd/kamcoback/label/dto/WorkerStatsDto.java b/src/main/java/com/kamco/cd/kamcoback/label/dto/WorkerStatsDto.java index efca81b2..f879f0ee 100644 --- a/src/main/java/com/kamco/cd/kamcoback/label/dto/WorkerStatsDto.java +++ b/src/main/java/com/kamco/cd/kamcoback/label/dto/WorkerStatsDto.java @@ -113,5 +113,17 @@ public class WorkerStatsDto { @Schema(description = "작업자 목록") private List workers; + + @Schema(description = "현재 페이지 번호 (0부터 시작)") + private Integer currentPage; + + @Schema(description = "페이지 크기") + private Integer pageSize; + + @Schema(description = "전체 데이터 수") + private Long totalElements; + + @Schema(description = "전체 페이지 수") + private Integer totalPages; } } diff --git a/src/main/java/com/kamco/cd/kamcoback/label/service/LabelAllocateService.java b/src/main/java/com/kamco/cd/kamcoback/label/service/LabelAllocateService.java index 8a994a1f..7da6156c 100644 --- a/src/main/java/com/kamco/cd/kamcoback/label/service/LabelAllocateService.java +++ b/src/main/java/com/kamco/cd/kamcoback/label/service/LabelAllocateService.java @@ -111,21 +111,23 @@ public class LabelAllocateService { } /** - * 작업자 목록 및 3일치 통계 조회 + * 작업자 통계 조회 * * @param analUid 분석 ID * @param workerType 작업자 유형 (LABELER/INSPECTOR) - * @param searchName 이름 검색 - * @param searchEmployeeNo 사번 검색 + * @param search 검색어 (이름 또는 사번) * @param sortType 정렬 조건 + * @param page 페이지 번호 (0부터 시작) + * @param size 페이지 크기 * @return 작업자 목록 및 통계 */ public WorkerListResponse getWorkerStatistics( Long analUid, String workerType, - String searchName, - String searchEmployeeNo, - String sortType) { + String search, + String sortType, + Integer page, + Integer size) { // 작업 진행 현황 조회 var progressInfo = labelAllocateCoreService.findWorkProgressInfo(analUid); @@ -133,7 +135,7 @@ public class LabelAllocateService { // 작업자 통계 조회 List workers = labelAllocateCoreService.findWorkerStatistics( - analUid, workerType, searchName, searchEmployeeNo, sortType); + analUid, workerType, search, sortType); // 각 작업자별 3일치 처리량 조회 LocalDate today = LocalDate.now(); @@ -166,7 +168,23 @@ public class LabelAllocateService { } } - return WorkerListResponse.builder().progressInfo(progressInfo).workers(workers).build(); + // 페이징 처리 + long totalElements = workers.size(); + int totalPages = (int) Math.ceil((double) totalElements / size); + int fromIndex = page * size; + int toIndex = Math.min(fromIndex + size, workers.size()); + + List pagedWorkers = + (fromIndex < workers.size()) ? workers.subList(fromIndex, toIndex) : List.of(); + + return WorkerListResponse.builder() + .progressInfo(progressInfo) + .workers(pagedWorkers) + .currentPage(page) + .pageSize(size) + .totalElements(totalElements) + .totalPages(totalPages) + .build(); } public InferenceDetail findInferenceDetail(String uuid) { diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/core/LabelAllocateCoreService.java b/src/main/java/com/kamco/cd/kamcoback/postgres/core/LabelAllocateCoreService.java index 5fd49cf5..d71471c0 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/core/LabelAllocateCoreService.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/core/LabelAllocateCoreService.java @@ -51,11 +51,10 @@ public class LabelAllocateCoreService { public List findWorkerStatistics( Long analUid, String workerType, - String searchName, - String searchEmployeeNo, + String search, String sortType) { return labelAllocateRepository.findWorkerStatistics( - analUid, workerType, searchName, searchEmployeeNo, sortType); + analUid, workerType, search, sortType); } public WorkProgressInfo findWorkProgressInfo(Long analUid) { diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/label/LabelAllocateRepositoryCustom.java b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/label/LabelAllocateRepositoryCustom.java index 72a1534e..a127e142 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/label/LabelAllocateRepositoryCustom.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/label/LabelAllocateRepositoryCustom.java @@ -28,7 +28,7 @@ public interface LabelAllocateRepositoryCustom { // 작업자 통계 조회 List findWorkerStatistics( - Long analUid, String workerType, String searchName, String searchEmployeeNo, String sortType); + Long analUid, String workerType, String search, String sortType); // 작업 진행 현황 조회 WorkProgressInfo findWorkProgressInfo(Long analUid); diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/label/LabelAllocateRepositoryImpl.java b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/label/LabelAllocateRepositoryImpl.java index 37f54a38..6d973dad 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/label/LabelAllocateRepositoryImpl.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/label/LabelAllocateRepositoryImpl.java @@ -190,8 +190,7 @@ public class LabelAllocateRepositoryImpl implements LabelAllocateRepositoryCusto public List findWorkerStatistics( Long analUid, String workerType, - String searchName, - String searchEmployeeNo, + String search, String sortType) { // 작업자 유형에 따른 필드 선택 @@ -205,14 +204,11 @@ public class LabelAllocateRepositoryImpl implements LabelAllocateRepositoryCusto ? labelingAssignmentEntity.inspectorUid.isNotNull() : labelingAssignmentEntity.workerUid.isNotNull(); - // 검색 조건 + // 검색 조건 (이름 또는 사번으로 검색) BooleanExpression searchCondition = null; - if (searchName != null && !searchName.isEmpty()) { - searchCondition = memberEntity.name.contains(searchName); - } - if (searchEmployeeNo != null && !searchEmployeeNo.isEmpty()) { - BooleanExpression empCondition = memberEntity.employeeNo.contains(searchEmployeeNo); - searchCondition = searchCondition == null ? empCondition : searchCondition.and(empCondition); + if (search != null && !search.isEmpty()) { + searchCondition = memberEntity.name.contains(search) + .or(memberEntity.employeeNo.contains(search)); } // 완료, 스킵, 남은 작업 계산 @@ -242,6 +238,8 @@ public class LabelAllocateRepositoryImpl implements LabelAllocateRepositoryCusto .sum(); // 기본 통계 조회 쿼리 + BooleanExpression analUidCondition = analUid != null ? labelingAssignmentEntity.analUid.eq(analUid) : null; + var baseQuery = queryFactory .select( @@ -258,7 +256,7 @@ public class LabelAllocateRepositoryImpl implements LabelAllocateRepositoryCusto "REVIEWER".equals(workerType) ? memberEntity.employeeNo.eq(labelingAssignmentEntity.inspectorUid) : memberEntity.employeeNo.eq(labelingAssignmentEntity.workerUid)) - .where(labelingAssignmentEntity.analUid.eq(analUid), workerCondition, searchCondition) + .where(analUidCondition, workerCondition, searchCondition) .groupBy(workerIdField, memberEntity.name); // 정렬 조건 적용 @@ -305,12 +303,14 @@ public class LabelAllocateRepositoryImpl implements LabelAllocateRepositoryCusto @Override public WorkProgressInfo findWorkProgressInfo(Long analUid) { + BooleanExpression analUidCondition = analUid != null ? labelingAssignmentEntity.analUid.eq(analUid) : null; + // 전체 배정 건수 Long totalAssigned = queryFactory .select(labelingAssignmentEntity.count()) .from(labelingAssignmentEntity) - .where(labelingAssignmentEntity.analUid.eq(analUid)) + .where(analUidCondition) .fetchOne(); // 완료 + 스킵 건수 @@ -319,7 +319,7 @@ public class LabelAllocateRepositoryImpl implements LabelAllocateRepositoryCusto .select(labelingAssignmentEntity.count()) .from(labelingAssignmentEntity) .where( - labelingAssignmentEntity.analUid.eq(analUid), + analUidCondition, labelingAssignmentEntity.workState.in("DONE", "SKIP")) .fetchOne(); @@ -329,7 +329,7 @@ public class LabelAllocateRepositoryImpl implements LabelAllocateRepositoryCusto .select(labelingAssignmentEntity.workerUid.countDistinct()) .from(labelingAssignmentEntity) .where( - labelingAssignmentEntity.analUid.eq(analUid), + analUidCondition, labelingAssignmentEntity.workerUid.isNotNull()) .fetchOne(); @@ -339,7 +339,7 @@ public class LabelAllocateRepositoryImpl implements LabelAllocateRepositoryCusto .select(labelingAssignmentEntity.count()) .from(labelingAssignmentEntity) .where( - labelingAssignmentEntity.analUid.eq(analUid), + analUidCondition, labelingAssignmentEntity.workerUid.isNotNull(), labelingAssignmentEntity.workState.notIn("DONE", "SKIP")) .fetchOne(); @@ -350,7 +350,7 @@ public class LabelAllocateRepositoryImpl implements LabelAllocateRepositoryCusto .select(labelingAssignmentEntity.inspectorUid.countDistinct()) .from(labelingAssignmentEntity) .where( - labelingAssignmentEntity.analUid.eq(analUid), + analUidCondition, labelingAssignmentEntity.inspectorUid.isNotNull()) .fetchOne(); @@ -360,7 +360,7 @@ public class LabelAllocateRepositoryImpl implements LabelAllocateRepositoryCusto .select(labelingAssignmentEntity.count()) .from(labelingAssignmentEntity) .where( - labelingAssignmentEntity.analUid.eq(analUid), + analUidCondition, labelingAssignmentEntity.inspectorUid.isNotNull(), labelingAssignmentEntity.workState.notIn("DONE")) .fetchOne(); @@ -400,12 +400,14 @@ public class LabelAllocateRepositoryImpl implements LabelAllocateRepositoryCusto ? labelingAssignmentEntity.inspectorUid.eq(workerId) : labelingAssignmentEntity.workerUid.eq(workerId); + BooleanExpression analUidCondition = analUid != null ? labelingAssignmentEntity.analUid.eq(analUid) : null; + Long count = queryFactory .select(labelingAssignmentEntity.count()) .from(labelingAssignmentEntity) .where( - labelingAssignmentEntity.analUid.eq(analUid), + analUidCondition, workerCondition, labelingAssignmentEntity.workState.in( LabelState.DONE.getId(), LabelState.SKIP.getId()),