From 3a458225c98d152de12059fe6b3c812360b1fed1 Mon Sep 17 00:00:00 2001 From: DanielLee <198891672+sanghyeonhd@users.noreply.github.com> Date: Fri, 2 Jan 2026 21:07:14 +0900 Subject: [PATCH] Build Error Fix --- .../label/LabelAllocateApiController.java | 226 +++--------------- .../kamcoback/label/dto/LabelAllocateDto.java | 2 + .../label/service/LabelAllocateService.java | 15 +- .../label/LabelAllocateRepositoryImpl.java | 3 +- 4 files changed, 43 insertions(+), 203 deletions(-) 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 9e359a82..88425c94 100644 --- a/src/main/java/com/kamco/cd/kamcoback/label/LabelAllocateApiController.java +++ b/src/main/java/com/kamco/cd/kamcoback/label/LabelAllocateApiController.java @@ -1,6 +1,6 @@ package com.kamco.cd.kamcoback.label; -import com.kamco.cd.kamcoback.code.dto.CommonCodeDto; +import com.kamco.cd.kamcoback.common.enums.RoleType; import com.kamco.cd.kamcoback.config.api.ApiResponseDto; import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto; import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.InferenceDetail; @@ -8,8 +8,6 @@ import com.kamco.cd.kamcoback.label.dto.WorkerStatsDto.WorkerListResponse; import com.kamco.cd.kamcoback.label.service.LabelAllocateService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.ExampleObject; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; @@ -36,185 +34,27 @@ public class LabelAllocateApiController { @Operation(summary = "배정 가능한 사용자 목록 조회", description = "라벨링 작업 배정을 위한 활성 상태의 사용자 목록을 조회합니다.") @ApiResponses( value = { - @ApiResponse( - responseCode = "200", - description = "조회 성공", - content = - @Content( - mediaType = "application/json", - schema = @Schema(implementation = CommonCodeDto.Basic.class), - examples = - @ExampleObject( - name = "사용자 목록 응답", - value = - """ - { - "data": [ - { - "userRole": "LABELER", - "employeeNo": "1234567", - "name": "김라벨" - }, - { - "userRole": "LABELER", - "employeeNo": "2345678", - "name": "이작업" - } - ] - } - """))), - @ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content), - @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) + @ApiResponse(responseCode = "200", description = "조회 성공"), + @ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음"), + @ApiResponse(responseCode = "500", description = "서버 오류") }) @GetMapping("/avail-user") public ApiResponseDto> availUserList( - @Parameter(description = "사용자 역할 (LABELER: 라벨러, REVIEWER: 검수자)", example = "LABELER") + @Parameter( + description = "사용자 역할", + example = "LABELER", + schema = @Schema(allowableValues = {"LABELER", "REVIEWER"})) @RequestParam - @Schema() String role) { return ApiResponseDto.ok(labelAllocateService.availUserList(role)); } - @Operation( - summary = "작업자 목록 및 3일치 통계 조회", - description = """ - 학습데이터 제작 현황 조회 API입니다. - """) + @Operation(summary = "작업현황관리(작업자 목록 및 3일치 통계 조회)", description = "학습데이터 제작 현황 조회 API입니다.") @ApiResponses( value = { - @ApiResponse( - responseCode = "200", - description = "조회 성공", - content = - @Content( - mediaType = "application/json", - schema = @Schema(implementation = WorkerListResponse.class), - examples = { - @ExampleObject( - name = "라벨러 조회 예시", - description = "라벨러 작업자들의 통계 정보", - value = - """ - { - "data": { - "progressInfo": { - "labelingProgressRate": 79.34, - "workStatus": "진행중", - "completedCount": 6554, - "totalAssignedCount": 8258, - "labelerCount": 5, - "remainingLabelCount": 1704, - "inspectorCount": 3, - "remainingInspectCount": 890 - }, - "workers": [ - { - "workerId": "1234567", - "workerName": "김라벨", - "workerType": "LABELER", - "totalAssigned": 1500, - "completed": 1100, - "skipped": 50, - "remaining": 350, - "history": { - "day1Ago": 281, - "day2Ago": 302, - "day3Ago": 294, - "average": 292 - }, - "isStagnated": false - }, - { - "workerId": "2345678", - "workerName": "이작업", - "workerType": "LABELER", - "totalAssigned": 2000, - "completed": 1850, - "skipped": 100, - "remaining": 50, - "history": { - "day1Ago": 5, - "day2Ago": 3, - "day3Ago": 8, - "average": 5 - }, - "isStagnated": true - } - ] - } - } - """), - @ExampleObject( - name = "검수자 조회 예시", - description = "검수자 작업자들의 통계 정보", - value = - """ - { - "data": { - "progressInfo": { - "labelingProgressRate": 79.34, - "workStatus": "진행중", - "completedCount": 6554, - "totalAssignedCount": 8258, - "labelerCount": 5, - "remainingLabelCount": 1704, - "inspectorCount": 3, - "remainingInspectCount": 890 - }, - "workers": [ - { - "workerId": "9876543", - "workerName": "박검수", - "workerType": "REVIEWER", - "totalAssigned": 1200, - "completed": 980, - "skipped": 20, - "remaining": 200, - "history": { - "day1Ago": 150, - "day2Ago": 145, - "day3Ago": 155, - "average": 150 - }, - "isStagnated": false - } - ] - } - } - """) - })), - @ApiResponse( - responseCode = "404", - description = "데이터를 찾을 수 없음", - content = - @Content( - examples = - @ExampleObject( - value = - """ - { - "error": { - "code": "NOT_FOUND", - "message": "해당 분석 ID의 데이터를 찾을 수 없습니다." - } - } - """))), - @ApiResponse( - responseCode = "500", - description = "서버 오류", - content = - @Content( - examples = - @ExampleObject( - value = - """ - { - "error": { - "code": "INTERNAL_SERVER_ERROR", - "message": "서버에 문제가 발생 하였습니다." - } - } - """))) + @ApiResponse(responseCode = "200", description = "조회 성공"), + @ApiResponse(responseCode = "404", description = "데이터를 찾을 수 없음"), + @ApiResponse(responseCode = "500", description = "서버 오류") }) @GetMapping("/admin/workers") public ApiResponseDto getWorkerStatistics( @@ -249,48 +89,40 @@ public class LabelAllocateApiController { @RequestParam(required = false) String sort) { - // type이 null이면 전체 조회 (일단 LABELER로 기본 설정) - String workerType = (type == null || type.isEmpty()) ? "LABELER" : type; + // type이 null이면 기본값으로 LABELER 설정 + String workerType = (type == null || type.isEmpty()) ? RoleType.LABELER.name() : type; return ApiResponseDto.ok( labelAllocateService.getWorkerStatistics( analUid, workerType, searchName, searchEmployeeNo, sort)); } + @Operation(summary = "라벨링 작업 배정", description = "라벨러 및 검수자에게 작업을 배정합니다.") @ApiResponses( value = { - @ApiResponse( - responseCode = "201", - description = "등록 성공", - content = - @Content( - mediaType = "application/json", - schema = @Schema(implementation = Long.class))), - @ApiResponse(responseCode = "400", description = "잘못된 요청 데이터", content = @Content), - @ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content), - @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) + @ApiResponse(responseCode = "200", description = "배정 성공"), + @ApiResponse(responseCode = "400", description = "잘못된 요청 데이터"), + @ApiResponse(responseCode = "500", description = "서버 오류") }) @PostMapping("/allocate") - public ApiResponseDto labelAllocate( - @io.swagger.v3.oas.annotations.parameters.RequestBody( - description = "라벨링 수량 할당", - required = true, - content = - @Content( - mediaType = "application/json", - schema = @Schema(implementation = LabelAllocateDto.AllocateDto.class))) - @RequestBody - LabelAllocateDto.AllocateDto dto) - throws Exception { - + public ApiResponseDto labelAllocate(@RequestBody LabelAllocateDto.AllocateDto dto) { labelAllocateService.allocateAsc( dto.getAutoType(), dto.getStage(), dto.getLabelers(), dto.getInspectors()); return ApiResponseDto.ok(null); } + @Operation(summary = "추론 상세 조회", description = "분석 ID에 해당하는 추론 상세 정보를 조회합니다.") + @ApiResponses( + value = { + @ApiResponse(responseCode = "200", description = "조회 성공"), + @ApiResponse(responseCode = "404", description = "데이터를 찾을 수 없음"), + @ApiResponse(responseCode = "500", description = "서버 오류") + }) @GetMapping - public ApiResponseDto findInferenceDetail(@RequestParam Long analUid) { + public ApiResponseDto findInferenceDetail( + @Parameter(description = "분석 ID", required = true, example = "3") @RequestParam + Long analUid) { return ApiResponseDto.ok(labelAllocateService.findInferenceDetail(analUid)); } } diff --git a/src/main/java/com/kamco/cd/kamcoback/label/dto/LabelAllocateDto.java b/src/main/java/com/kamco/cd/kamcoback/label/dto/LabelAllocateDto.java index 5b508a07..80d96744 100644 --- a/src/main/java/com/kamco/cd/kamcoback/label/dto/LabelAllocateDto.java +++ b/src/main/java/com/kamco/cd/kamcoback/label/dto/LabelAllocateDto.java @@ -42,8 +42,10 @@ public class LabelAllocateDto { @Getter @AllArgsConstructor public enum LabelState implements EnumType { + WAIT("대기"), ASSIGNED("배정"), SKIP("스킵"), + DONE("완료"), COMPLETE("완료"); private String desc; 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 a51a2ae7..f01de1cd 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 @@ -21,6 +21,9 @@ import org.springframework.transaction.annotation.Transactional; @Transactional(readOnly = true) public class LabelAllocateService { + private static final int STAGNATION_THRESHOLD = 10; // 정체 판단 기준 (3일 평균 처리량) + private static final int BATCH_SIZE = 100; // 배정 배치 크기 + private final LabelAllocateCoreService labelAllocateCoreService; public LabelAllocateService(LabelAllocateCoreService labelAllocateCoreService) { @@ -30,15 +33,17 @@ public class LabelAllocateService { /** * 도엽 기준 asc sorting 해서 할당 수만큼 배정하는 로직 * - * @param targetUsers + * @param autoType 자동/수동 배정 타입 + * @param stage 회차 + * @param targetUsers 라벨러 목록 + * @param targetInspectors 검수자 목록 */ @Transactional public void allocateAsc( String autoType, Integer stage, List targetUsers, - List targetInspectors) - throws Exception { + List targetInspectors) { Long lastId = null; // geom 잔여건수 != 프론트에서 넘어 온 총 건수 -> return @@ -137,8 +142,8 @@ public class LabelAllocateService { worker.setHistory(history); - // 정체 여부 판단 (3일 평균이 특정 기준 미만일 때 - 예: 10건 미만) - if (average < 10) { + // 정체 여부 판단 (3일 평균이 STAGNATION_THRESHOLD 미만일 때) + if (average < STAGNATION_THRESHOLD) { worker.setIsStagnated(true); } } 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 88d07305..c98f5308 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 @@ -375,7 +375,8 @@ public class LabelAllocateRepositoryImpl implements LabelAllocateRepositoryCusto .where( labelingAssignmentEntity.analUid.eq(analUid), workerCondition, - labelingAssignmentEntity.workState.in("DONE", "SKIP"), + labelingAssignmentEntity.workState.in( + LabelState.DONE.getId(), LabelState.SKIP.getId()), labelingAssignmentEntity.modifiedDate.between(startOfDay, endOfDay)) .fetchOne();