작업현황관리 수정

This commit is contained in:
DanielLee
2026-01-05 11:41:50 +09:00
parent 88cf9a4487
commit 67eb99e243
6 changed files with 71 additions and 36 deletions

View File

@@ -63,7 +63,7 @@ public class LabelAllocateApiController {
}) })
@GetMapping("/admin/workers") @GetMapping("/admin/workers")
public ApiResponseDto<WorkerListResponse> getWorkerStatistics( public ApiResponseDto<WorkerListResponse> getWorkerStatistics(
@Parameter(description = "분석 ID (필수)", required = true, example = "3") @RequestParam @Parameter(description = "분석 ID (선택)", example = "3") @RequestParam(required = false)
Long analUid, Long analUid,
@Parameter( @Parameter(
description = "작업자 유형 (선택) - 미입력 시 LABELER로 조회", description = "작업자 유형 (선택) - 미입력 시 LABELER로 조회",
@@ -74,11 +74,9 @@ public class LabelAllocateApiController {
defaultValue = "LABELER")) defaultValue = "LABELER"))
@RequestParam(required = false) @RequestParam(required = false)
String type, String type,
@Parameter(description = "작업자 이름 검색 (부분 일치)", example = "김라벨") @RequestParam(required = false) @Parameter(description = "검색어 (작업자 이름 또는 사번으로 검색, 부분 일치)", example = "김라벨")
String searchName,
@Parameter(description = "작업자 사번 검색 (부분 일치)", example = "1234567")
@RequestParam(required = false) @RequestParam(required = false)
String searchEmployeeNo, String search,
@Parameter( @Parameter(
description = "정렬 조건 (선택) - 미입력 시 이름 오름차순", description = "정렬 조건 (선택) - 미입력 시 이름 오름차순",
example = "REMAINING_DESC", example = "REMAINING_DESC",
@@ -92,14 +90,20 @@ public class LabelAllocateApiController {
}, },
defaultValue = "NAME_ASC")) defaultValue = "NAME_ASC"))
@RequestParam(required = false) @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 설정 // type이 null이면 기본값으로 LABELER 설정
String workerType = (type == null || type.isEmpty()) ? RoleType.LABELER.name() : type; String workerType = (type == null || type.isEmpty()) ? RoleType.LABELER.name() : type;
return ApiResponseDto.ok( return ApiResponseDto.ok(
labelAllocateService.getWorkerStatistics( labelAllocateService.getWorkerStatistics(
analUid, workerType, searchName, searchEmployeeNo, sort)); analUid, workerType, search, sort, page, size));
} }
@Operation(summary = "라벨링작업 관리 > 작업 배정", description = "라벨링작업 관리 > 작업 배정") @Operation(summary = "라벨링작업 관리 > 작업 배정", description = "라벨링작업 관리 > 작업 배정")

View File

@@ -113,5 +113,17 @@ public class WorkerStatsDto {
@Schema(description = "작업자 목록") @Schema(description = "작업자 목록")
private List<WorkerStatistics> workers; private List<WorkerStatistics> workers;
@Schema(description = "현재 페이지 번호 (0부터 시작)")
private Integer currentPage;
@Schema(description = "페이지 크기")
private Integer pageSize;
@Schema(description = "전체 데이터 수")
private Long totalElements;
@Schema(description = "전체 페이지 수")
private Integer totalPages;
} }
} }

View File

@@ -107,21 +107,23 @@ public class LabelAllocateService {
} }
/** /**
* 작업자 목록 및 3일치 통계 조회 * 작업자 통계 조회
* *
* @param analUid 분석 ID * @param analUid 분석 ID
* @param workerType 작업자 유형 (LABELER/INSPECTOR) * @param workerType 작업자 유형 (LABELER/INSPECTOR)
* @param searchName 이름 검색 * @param search 검색어 (이름 또는 사번)
* @param searchEmployeeNo 사번 검색
* @param sortType 정렬 조건 * @param sortType 정렬 조건
* @param page 페이지 번호 (0부터 시작)
* @param size 페이지 크기
* @return 작업자 목록 및 통계 * @return 작업자 목록 및 통계
*/ */
public WorkerListResponse getWorkerStatistics( public WorkerListResponse getWorkerStatistics(
Long analUid, Long analUid,
String workerType, String workerType,
String searchName, String search,
String searchEmployeeNo, String sortType,
String sortType) { Integer page,
Integer size) {
// 작업 진행 현황 조회 // 작업 진행 현황 조회
var progressInfo = labelAllocateCoreService.findWorkProgressInfo(analUid); var progressInfo = labelAllocateCoreService.findWorkProgressInfo(analUid);
@@ -129,7 +131,7 @@ public class LabelAllocateService {
// 작업자 통계 조회 // 작업자 통계 조회
List<WorkerStatistics> workers = List<WorkerStatistics> workers =
labelAllocateCoreService.findWorkerStatistics( labelAllocateCoreService.findWorkerStatistics(
analUid, workerType, searchName, searchEmployeeNo, sortType); analUid, workerType, search, sortType);
// 각 작업자별 3일치 처리량 조회 // 각 작업자별 3일치 처리량 조회
LocalDate today = LocalDate.now(); LocalDate today = LocalDate.now();
@@ -162,7 +164,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<WorkerStatistics> 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( public InferenceDetail findInferenceDetail(

View File

@@ -57,11 +57,10 @@ public class LabelAllocateCoreService {
public List<WorkerStatistics> findWorkerStatistics( public List<WorkerStatistics> findWorkerStatistics(
Long analUid, Long analUid,
String workerType, String workerType,
String searchName, String search,
String searchEmployeeNo,
String sortType) { String sortType) {
return labelAllocateRepository.findWorkerStatistics( return labelAllocateRepository.findWorkerStatistics(
analUid, workerType, searchName, searchEmployeeNo, sortType); analUid, workerType, search, sortType);
} }
public WorkProgressInfo findWorkProgressInfo(Long analUid) { public WorkProgressInfo findWorkProgressInfo(Long analUid) {

View File

@@ -34,7 +34,7 @@ public interface LabelAllocateRepositoryCustom {
// 작업자 통계 조회 // 작업자 통계 조회
List<WorkerStatistics> findWorkerStatistics( List<WorkerStatistics> findWorkerStatistics(
Long analUid, String workerType, String searchName, String searchEmployeeNo, String sortType); Long analUid, String workerType, String search, String sortType);
// 작업 진행 현황 조회 // 작업 진행 현황 조회
WorkProgressInfo findWorkProgressInfo(Long analUid); WorkProgressInfo findWorkProgressInfo(Long analUid);

View File

@@ -206,8 +206,7 @@ public class LabelAllocateRepositoryImpl implements LabelAllocateRepositoryCusto
public List<WorkerStatistics> findWorkerStatistics( public List<WorkerStatistics> findWorkerStatistics(
Long analUid, Long analUid,
String workerType, String workerType,
String searchName, String search,
String searchEmployeeNo,
String sortType) { String sortType) {
// 작업자 유형에 따른 필드 선택 // 작업자 유형에 따른 필드 선택
@@ -221,14 +220,11 @@ public class LabelAllocateRepositoryImpl implements LabelAllocateRepositoryCusto
? labelingAssignmentEntity.inspectorUid.isNotNull() ? labelingAssignmentEntity.inspectorUid.isNotNull()
: labelingAssignmentEntity.workerUid.isNotNull(); : labelingAssignmentEntity.workerUid.isNotNull();
// 검색 조건 // 검색 조건 (이름 또는 사번으로 검색)
BooleanExpression searchCondition = null; BooleanExpression searchCondition = null;
if (searchName != null && !searchName.isEmpty()) { if (search != null && !search.isEmpty()) {
searchCondition = memberEntity.name.contains(searchName); searchCondition = memberEntity.name.contains(search)
} .or(memberEntity.employeeNo.contains(search));
if (searchEmployeeNo != null && !searchEmployeeNo.isEmpty()) {
BooleanExpression empCondition = memberEntity.employeeNo.contains(searchEmployeeNo);
searchCondition = searchCondition == null ? empCondition : searchCondition.and(empCondition);
} }
// 완료, 스킵, 남은 작업 계산 // 완료, 스킵, 남은 작업 계산
@@ -258,6 +254,8 @@ public class LabelAllocateRepositoryImpl implements LabelAllocateRepositoryCusto
.sum(); .sum();
// 기본 통계 조회 쿼리 // 기본 통계 조회 쿼리
BooleanExpression analUidCondition = analUid != null ? labelingAssignmentEntity.analUid.eq(analUid) : null;
var baseQuery = var baseQuery =
queryFactory queryFactory
.select( .select(
@@ -274,7 +272,7 @@ public class LabelAllocateRepositoryImpl implements LabelAllocateRepositoryCusto
"REVIEWER".equals(workerType) "REVIEWER".equals(workerType)
? memberEntity.employeeNo.eq(labelingAssignmentEntity.inspectorUid) ? memberEntity.employeeNo.eq(labelingAssignmentEntity.inspectorUid)
: memberEntity.employeeNo.eq(labelingAssignmentEntity.workerUid)) : memberEntity.employeeNo.eq(labelingAssignmentEntity.workerUid))
.where(labelingAssignmentEntity.analUid.eq(analUid), workerCondition, searchCondition) .where(analUidCondition, workerCondition, searchCondition)
.groupBy(workerIdField, memberEntity.name); .groupBy(workerIdField, memberEntity.name);
// 정렬 조건 적용 // 정렬 조건 적용
@@ -321,12 +319,14 @@ public class LabelAllocateRepositoryImpl implements LabelAllocateRepositoryCusto
@Override @Override
public WorkProgressInfo findWorkProgressInfo(Long analUid) { public WorkProgressInfo findWorkProgressInfo(Long analUid) {
BooleanExpression analUidCondition = analUid != null ? labelingAssignmentEntity.analUid.eq(analUid) : null;
// 전체 배정 건수 // 전체 배정 건수
Long totalAssigned = Long totalAssigned =
queryFactory queryFactory
.select(labelingAssignmentEntity.count()) .select(labelingAssignmentEntity.count())
.from(labelingAssignmentEntity) .from(labelingAssignmentEntity)
.where(labelingAssignmentEntity.analUid.eq(analUid)) .where(analUidCondition)
.fetchOne(); .fetchOne();
// 완료 + 스킵 건수 // 완료 + 스킵 건수
@@ -335,7 +335,7 @@ public class LabelAllocateRepositoryImpl implements LabelAllocateRepositoryCusto
.select(labelingAssignmentEntity.count()) .select(labelingAssignmentEntity.count())
.from(labelingAssignmentEntity) .from(labelingAssignmentEntity)
.where( .where(
labelingAssignmentEntity.analUid.eq(analUid), analUidCondition,
labelingAssignmentEntity.workState.in("DONE", "SKIP")) labelingAssignmentEntity.workState.in("DONE", "SKIP"))
.fetchOne(); .fetchOne();
@@ -345,7 +345,7 @@ public class LabelAllocateRepositoryImpl implements LabelAllocateRepositoryCusto
.select(labelingAssignmentEntity.workerUid.countDistinct()) .select(labelingAssignmentEntity.workerUid.countDistinct())
.from(labelingAssignmentEntity) .from(labelingAssignmentEntity)
.where( .where(
labelingAssignmentEntity.analUid.eq(analUid), analUidCondition,
labelingAssignmentEntity.workerUid.isNotNull()) labelingAssignmentEntity.workerUid.isNotNull())
.fetchOne(); .fetchOne();
@@ -355,7 +355,7 @@ public class LabelAllocateRepositoryImpl implements LabelAllocateRepositoryCusto
.select(labelingAssignmentEntity.count()) .select(labelingAssignmentEntity.count())
.from(labelingAssignmentEntity) .from(labelingAssignmentEntity)
.where( .where(
labelingAssignmentEntity.analUid.eq(analUid), analUidCondition,
labelingAssignmentEntity.workerUid.isNotNull(), labelingAssignmentEntity.workerUid.isNotNull(),
labelingAssignmentEntity.workState.notIn("DONE", "SKIP")) labelingAssignmentEntity.workState.notIn("DONE", "SKIP"))
.fetchOne(); .fetchOne();
@@ -366,7 +366,7 @@ public class LabelAllocateRepositoryImpl implements LabelAllocateRepositoryCusto
.select(labelingAssignmentEntity.inspectorUid.countDistinct()) .select(labelingAssignmentEntity.inspectorUid.countDistinct())
.from(labelingAssignmentEntity) .from(labelingAssignmentEntity)
.where( .where(
labelingAssignmentEntity.analUid.eq(analUid), analUidCondition,
labelingAssignmentEntity.inspectorUid.isNotNull()) labelingAssignmentEntity.inspectorUid.isNotNull())
.fetchOne(); .fetchOne();
@@ -376,7 +376,7 @@ public class LabelAllocateRepositoryImpl implements LabelAllocateRepositoryCusto
.select(labelingAssignmentEntity.count()) .select(labelingAssignmentEntity.count())
.from(labelingAssignmentEntity) .from(labelingAssignmentEntity)
.where( .where(
labelingAssignmentEntity.analUid.eq(analUid), analUidCondition,
labelingAssignmentEntity.inspectorUid.isNotNull(), labelingAssignmentEntity.inspectorUid.isNotNull(),
labelingAssignmentEntity.workState.notIn("DONE")) labelingAssignmentEntity.workState.notIn("DONE"))
.fetchOne(); .fetchOne();
@@ -416,12 +416,14 @@ public class LabelAllocateRepositoryImpl implements LabelAllocateRepositoryCusto
? labelingAssignmentEntity.inspectorUid.eq(workerId) ? labelingAssignmentEntity.inspectorUid.eq(workerId)
: labelingAssignmentEntity.workerUid.eq(workerId); : labelingAssignmentEntity.workerUid.eq(workerId);
BooleanExpression analUidCondition = analUid != null ? labelingAssignmentEntity.analUid.eq(analUid) : null;
Long count = Long count =
queryFactory queryFactory
.select(labelingAssignmentEntity.count()) .select(labelingAssignmentEntity.count())
.from(labelingAssignmentEntity) .from(labelingAssignmentEntity)
.where( .where(
labelingAssignmentEntity.analUid.eq(analUid), analUidCondition,
workerCondition, workerCondition,
labelingAssignmentEntity.workState.in( labelingAssignmentEntity.workState.in(
LabelState.DONE.getId(), LabelState.SKIP.getId()), LabelState.DONE.getId(), LabelState.SKIP.getId()),