라벨 재할당 가능한 대상자 목록 API

This commit is contained in:
2026-01-06 15:31:52 +09:00
parent 89290678e4
commit 4a5bbd4cf3
6 changed files with 108 additions and 9 deletions

View File

@@ -223,4 +223,20 @@ public class LabelAllocateApiController {
LabelAllocateDto.searchReq searchReq = new LabelAllocateDto.searchReq(page, size, ""); LabelAllocateDto.searchReq searchReq = new LabelAllocateDto.searchReq(page, size, "");
return ApiResponseDto.ok(labelAllocateService.findDaliyList(searchReq, uuid, userId, type)); 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<List<LabelAllocateDto.MoveUserList>> 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));
}
} }

View File

@@ -308,4 +308,16 @@ public class LabelAllocateDto {
return PageRequest.of(page, size); 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;
}
} }

View File

@@ -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.InferenceDetail;
import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.LabelerDetail; 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.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.TargetUser;
import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.UserList; import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.UserList;
import com.kamco.cd.kamcoback.label.dto.WorkerStatsDto.WorkerListResponse; import com.kamco.cd.kamcoback.label.dto.WorkerStatsDto.WorkerListResponse;
@@ -159,4 +160,8 @@ public class LabelAllocateService {
return labelAllocateCoreService.findInspectorDailyStat(searchReq, uuid, userId); return labelAllocateCoreService.findInspectorDailyStat(searchReq, uuid, userId);
} }
} }
public List<MoveUserList> moveAvailUserList(String userId, String uuid) {
return labelAllocateCoreService.moveAvailUserList(userId, uuid);
}
} }

View File

@@ -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.InferenceDetail;
import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.LabelerDetail; 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.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.UserList;
import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.searchReq; import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.searchReq;
import com.kamco.cd.kamcoback.label.dto.WorkerStatsDto.ProjectInfo; import com.kamco.cd.kamcoback.label.dto.WorkerStatsDto.ProjectInfo;
@@ -126,4 +127,8 @@ public class LabelAllocateCoreService {
public LabelerDetail findInspectorDetail(String userId, String uuid) { public LabelerDetail findInspectorDetail(String userId, String uuid) {
return labelAllocateRepository.findInspectorDetail(userId, uuid); return labelAllocateRepository.findInspectorDetail(userId, uuid);
} }
public List<MoveUserList> moveAvailUserList(String userId, String uuid) {
return labelAllocateRepository.moveAvailUserList(userId, uuid);
}
} }

View File

@@ -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.InferenceDetail;
import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.LabelerDetail; 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.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.UserList;
import com.kamco.cd.kamcoback.label.dto.WorkerStatsDto.ProjectInfo; import com.kamco.cd.kamcoback.label.dto.WorkerStatsDto.ProjectInfo;
import com.kamco.cd.kamcoback.label.dto.WorkerStatsDto.WorkProgressInfo; import com.kamco.cd.kamcoback.label.dto.WorkerStatsDto.WorkProgressInfo;
@@ -76,4 +77,6 @@ public interface LabelAllocateRepositoryCustom {
LabelAllocateDto.searchReq searchReq, String uuid, String userId); LabelAllocateDto.searchReq searchReq, String uuid, String userId);
LabelerDetail findInspectorDetail(String userId, String uuid); LabelerDetail findInspectorDetail(String userId, String uuid);
List<MoveUserList> moveAvailUserList(String userId, String uuid);
} }

View File

@@ -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.LabelState;
import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.LabelerDetail; 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.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.UserList;
import com.kamco.cd.kamcoback.label.dto.WorkerStatsDto.ProjectInfo; import com.kamco.cd.kamcoback.label.dto.WorkerStatsDto.ProjectInfo;
import com.kamco.cd.kamcoback.label.dto.WorkerStatsDto.WorkProgressInfo; import com.kamco.cd.kamcoback.label.dto.WorkerStatsDto.WorkProgressInfo;
@@ -114,11 +115,11 @@ public class LabelAllocateRepositoryImpl implements LabelAllocateRepositoryCusto
connection -> { connection -> {
String sql = String sql =
""" """
insert into tb_labeling_assignment insert into tb_labeling_assignment
(assignment_uid, inference_geom_uid, worker_uid, (assignment_uid, inference_geom_uid, worker_uid,
work_state, assign_group_id, anal_uid) work_state, assign_group_id, anal_uid)
values (?, ?, ?, ?, ?, ?) values (?, ?, ?, ?, ?, ?)
"""; """;
try (PreparedStatement ps = connection.prepareStatement(sql)) { try (PreparedStatement ps = connection.prepareStatement(sql)) {
int batchSize = 0; int batchSize = 0;
@@ -583,8 +584,8 @@ public class LabelAllocateRepositoryImpl implements LabelAllocateRepositoryCusto
Expressions.numberTemplate( Expressions.numberTemplate(
Double.class, Double.class,
"round({0} / {1}, 2)", "round({0} / {1}, 2)",
labelingAssignmentEntity.count(), completeCnt,
completeCnt)); labelingAssignmentEntity.count()));
// analUid로 분석 정보 조회 // analUid로 분석 정보 조회
MapSheetAnalInferenceEntity analEntity = MapSheetAnalInferenceEntity analEntity =
@@ -988,8 +989,8 @@ public class LabelAllocateRepositoryImpl implements LabelAllocateRepositoryCusto
Expressions.numberTemplate( Expressions.numberTemplate(
Double.class, Double.class,
"round({0} / {1}, 2)", "round({0} / {1}, 2)",
labelingAssignmentEntity.count(), completeCnt,
completeCnt)); labelingAssignmentEntity.count()));
// analUid로 분석 정보 조회 // analUid로 분석 정보 조회
MapSheetAnalInferenceEntity analEntity = MapSheetAnalInferenceEntity analEntity =
@@ -1036,4 +1037,61 @@ public class LabelAllocateRepositoryImpl implements LabelAllocateRepositoryCusto
.groupBy(inspector.userRole, inspector.name, inspector.employeeNo) .groupBy(inspector.userRole, inspector.name, inspector.employeeNo)
.fetchOne(); .fetchOne();
} }
@Override
public List<MoveUserList> moveAvailUserList(String userId, String uuid) {
NumberExpression<Long> totalCnt = labelingAssignmentEntity.count();
NumberExpression<Long> completeCnt =
new CaseBuilder()
.when(labelingAssignmentEntity.workState.eq(LabelState.COMPLETE.getId()))
.then(1L)
.otherwise(0L)
.sum();
NumberExpression<Double> 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<Long> 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();
}
} }