From 4a5bbd4cf383d5fea40b667d15985d810a305abe Mon Sep 17 00:00:00 2001 From: "gayoun.park" Date: Tue, 6 Jan 2026 15:31:52 +0900 Subject: [PATCH] =?UTF-8?q?=EB=9D=BC=EB=B2=A8=20=EC=9E=AC=ED=95=A0?= =?UTF-8?q?=EB=8B=B9=20=EA=B0=80=EB=8A=A5=ED=95=9C=20=EB=8C=80=EC=83=81?= =?UTF-8?q?=EC=9E=90=20=EB=AA=A9=EB=A1=9D=20API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../label/LabelAllocateApiController.java | 16 ++++ .../kamcoback/label/dto/LabelAllocateDto.java | 12 +++ .../label/service/LabelAllocateService.java | 5 ++ .../core/LabelAllocateCoreService.java | 5 ++ .../label/LabelAllocateRepositoryCustom.java | 3 + .../label/LabelAllocateRepositoryImpl.java | 76 ++++++++++++++++--- 6 files changed, 108 insertions(+), 9 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 393ac3d7..ce6636c4 100644 --- a/src/main/java/com/kamco/cd/kamcoback/label/LabelAllocateApiController.java +++ b/src/main/java/com/kamco/cd/kamcoback/label/LabelAllocateApiController.java @@ -223,4 +223,20 @@ public class LabelAllocateApiController { LabelAllocateDto.searchReq searchReq = new LabelAllocateDto.searchReq(page, size, ""); return ApiResponseDto.ok(labelAllocateService.findDaliyList(searchReq, uuid, userId, type)); } + + @Operation(summary = "이관 가능한 사용자 목록 조회", description = "이관 가능한 사용자 목록 조회") + @ApiResponses( + value = { + @ApiResponse(responseCode = "200", description = "조회 성공"), + @ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음"), + @ApiResponse(responseCode = "500", description = "서버 오류") + }) + @GetMapping("/move-user") + public ApiResponseDto> availMoveUserList( + @Parameter(description = "해당 사용자 사번", example = "01022223333") @RequestParam String userId, + @Parameter(description = "회차 마스터 key", example = "f97dc186-e6d3-4645-9737-3173dde8dc64") + @RequestParam + String uuid) { + return ApiResponseDto.ok(labelAllocateService.moveAvailUserList(userId, uuid)); + } } 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 3bbc7aab..9153a305 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 @@ -308,4 +308,16 @@ public class LabelAllocateDto { return PageRequest.of(page, size); } } + + @Getter + @Setter + @AllArgsConstructor + public static class MoveUserList { + + private String userRole; + private String employeeNo; + private String name; + private Long remainCnt; + private Double percent; + } } 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 a0dfadf2..445f208f 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 @@ -7,6 +7,7 @@ import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.AllocateInfoDto; import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.InferenceDetail; import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.LabelerDetail; import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.LabelingStatDto; +import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.MoveUserList; import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.TargetUser; import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.UserList; import com.kamco.cd.kamcoback.label.dto.WorkerStatsDto.WorkerListResponse; @@ -159,4 +160,8 @@ public class LabelAllocateService { return labelAllocateCoreService.findInspectorDailyStat(searchReq, uuid, userId); } } + + public List moveAvailUserList(String userId, String uuid) { + return labelAllocateCoreService.moveAvailUserList(userId, 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 d7e68d77..af40387a 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 @@ -5,6 +5,7 @@ import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.AllocateInfoDto; import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.InferenceDetail; import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.LabelerDetail; import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.LabelingStatDto; +import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.MoveUserList; import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.UserList; import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.searchReq; import com.kamco.cd.kamcoback.label.dto.WorkerStatsDto.ProjectInfo; @@ -126,4 +127,8 @@ public class LabelAllocateCoreService { public LabelerDetail findInspectorDetail(String userId, String uuid) { return labelAllocateRepository.findInspectorDetail(userId, uuid); } + + public List moveAvailUserList(String userId, String uuid) { + return labelAllocateRepository.moveAvailUserList(userId, uuid); + } } 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 4f296843..d2753114 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 @@ -5,6 +5,7 @@ import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.AllocateInfoDto; import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.InferenceDetail; import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.LabelerDetail; import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.LabelingStatDto; +import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.MoveUserList; import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.UserList; import com.kamco.cd.kamcoback.label.dto.WorkerStatsDto.ProjectInfo; import com.kamco.cd.kamcoback.label.dto.WorkerStatsDto.WorkProgressInfo; @@ -76,4 +77,6 @@ public interface LabelAllocateRepositoryCustom { LabelAllocateDto.searchReq searchReq, String uuid, String userId); LabelerDetail findInspectorDetail(String userId, String uuid); + + List moveAvailUserList(String userId, String uuid); } 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 418f791b..1d422a48 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 @@ -14,6 +14,7 @@ import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.InspectState; import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.LabelState; import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.LabelerDetail; import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.LabelingStatDto; +import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.MoveUserList; import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.UserList; import com.kamco.cd.kamcoback.label.dto.WorkerStatsDto.ProjectInfo; import com.kamco.cd.kamcoback.label.dto.WorkerStatsDto.WorkProgressInfo; @@ -114,11 +115,11 @@ public class LabelAllocateRepositoryImpl implements LabelAllocateRepositoryCusto connection -> { String sql = """ - insert into tb_labeling_assignment - (assignment_uid, inference_geom_uid, worker_uid, - work_state, assign_group_id, anal_uid) - values (?, ?, ?, ?, ?, ?) - """; + insert into tb_labeling_assignment + (assignment_uid, inference_geom_uid, worker_uid, + work_state, assign_group_id, anal_uid) + values (?, ?, ?, ?, ?, ?) + """; try (PreparedStatement ps = connection.prepareStatement(sql)) { int batchSize = 0; @@ -583,8 +584,8 @@ public class LabelAllocateRepositoryImpl implements LabelAllocateRepositoryCusto Expressions.numberTemplate( Double.class, "round({0} / {1}, 2)", - labelingAssignmentEntity.count(), - completeCnt)); + completeCnt, + labelingAssignmentEntity.count())); // analUid로 분석 정보 조회 MapSheetAnalInferenceEntity analEntity = @@ -988,8 +989,8 @@ public class LabelAllocateRepositoryImpl implements LabelAllocateRepositoryCusto Expressions.numberTemplate( Double.class, "round({0} / {1}, 2)", - labelingAssignmentEntity.count(), - completeCnt)); + completeCnt, + labelingAssignmentEntity.count())); // analUid로 분석 정보 조회 MapSheetAnalInferenceEntity analEntity = @@ -1036,4 +1037,61 @@ public class LabelAllocateRepositoryImpl implements LabelAllocateRepositoryCusto .groupBy(inspector.userRole, inspector.name, inspector.employeeNo) .fetchOne(); } + + @Override + public List moveAvailUserList(String userId, String uuid) { + + NumberExpression totalCnt = labelingAssignmentEntity.count(); + NumberExpression completeCnt = + new CaseBuilder() + .when(labelingAssignmentEntity.workState.eq(LabelState.COMPLETE.getId())) + .then(1L) + .otherwise(0L) + .sum(); + + NumberExpression percent = + new CaseBuilder() + .when(completeCnt.eq(0L)) + .then(0.0) + .otherwise( + Expressions.numberTemplate( + Double.class, + "round(({0} * 100.0) / nullif({1}, 0), 2)", + completeCnt, + totalCnt)); + + // remainCnt + Expression remainCnt = totalCnt.subtract(completeCnt); + + // analUid로 분석 정보 조회 + MapSheetAnalInferenceEntity analEntity = + queryFactory + .selectFrom(mapSheetAnalInferenceEntity) + .where(mapSheetAnalInferenceEntity.uuid.eq(UUID.fromString(uuid))) + .fetchOne(); + + if (Objects.isNull(analEntity)) { + throw new EntityNotFoundException("MapSheetAnalInferenceEntity not found for analUid: "); + } + + return queryFactory + .select( + Projections.constructor( + MoveUserList.class, + memberEntity.userRole, + memberEntity.employeeNo, + memberEntity.name, + remainCnt, + percent)) + .from(labelingAssignmentEntity) + .innerJoin(memberEntity) + .on(labelingAssignmentEntity.workerUid.eq(memberEntity.employeeNo)) + .where( + labelingAssignmentEntity.analUid.eq(analEntity.getId()), + labelingAssignmentEntity.workerUid.ne(userId)) + .groupBy(memberEntity.userRole, memberEntity.employeeNo, memberEntity.name) + .having(completeCnt.multiply(2).goe(totalCnt)) // 진행률 평균 이상인 것들만 조회 => percent 를 바로 쓰면 + .orderBy(completeCnt.desc()) + .fetch(); + } }