projectinfo uuid조회 추가
This commit is contained in:
@@ -55,7 +55,9 @@ public class LabelAllocateApiController {
|
|||||||
return ApiResponseDto.ok(labelAllocateService.availUserList(role));
|
return ApiResponseDto.ok(labelAllocateService.availUserList(role));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Operation(summary = "작업현황 관리 > 프로젝트 및 진행 상황 정보", description = "작업현황 관리 > 프로젝트 및 진행 상황 정보")
|
@Operation(
|
||||||
|
summary = "작업현황 관리 > 프로젝트 및 진행 상황 정보",
|
||||||
|
description = "작업현황 관리 > 프로젝트 및 진행 상황 정보. UUID를 입력하면 해당 프로젝트 정보를 조회하고, 미입력 시 최신 프로젝트를 조회합니다.")
|
||||||
@ApiResponses(
|
@ApiResponses(
|
||||||
value = {
|
value = {
|
||||||
@ApiResponse(responseCode = "200", description = "조회 성공"),
|
@ApiResponse(responseCode = "200", description = "조회 성공"),
|
||||||
@@ -64,8 +66,11 @@ public class LabelAllocateApiController {
|
|||||||
})
|
})
|
||||||
@GetMapping("/projectinfo")
|
@GetMapping("/projectinfo")
|
||||||
public ApiResponseDto<WorkerListResponse> getWorkerStatistics(
|
public ApiResponseDto<WorkerListResponse> getWorkerStatistics(
|
||||||
// @Parameter(description = "분석 ID (선택)", example = "3") @RequestParam(required = false)
|
@Parameter(
|
||||||
// Long analUid,
|
description = "프로젝트 UUID (선택) - 미입력 시 최신 프로젝트 조회",
|
||||||
|
example = "f97dc186-e6d3-4645-9737-3173dde8dc64")
|
||||||
|
@RequestParam(required = false)
|
||||||
|
String uuid,
|
||||||
@Parameter(
|
@Parameter(
|
||||||
description = "작업자 유형 (선택) - 미입력 시 LABELER로 조회",
|
description = "작업자 유형 (선택) - 미입력 시 LABELER로 조회",
|
||||||
example = "LABELER",
|
example = "LABELER",
|
||||||
@@ -99,7 +104,7 @@ public class LabelAllocateApiController {
|
|||||||
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(null, workerType, search, sort));
|
labelAllocateService.getWorkerStatisticsByUuid(uuid, workerType, search, sort));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Operation(summary = "라벨링작업 관리 > 작업 배정", description = "라벨링작업 관리 > 작업 배정")
|
@Operation(summary = "라벨링작업 관리 > 작업 배정", description = "라벨링작업 관리 > 작업 배정")
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.LabelingStatDto;
|
|||||||
import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.MoveInfo;
|
import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.MoveInfo;
|
||||||
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.ProjectInfo;
|
||||||
|
import com.kamco.cd.kamcoback.label.dto.WorkerStatsDto.WorkProgressInfo;
|
||||||
import com.kamco.cd.kamcoback.label.dto.WorkerStatsDto.WorkerListResponse;
|
import com.kamco.cd.kamcoback.label.dto.WorkerStatsDto.WorkerListResponse;
|
||||||
import com.kamco.cd.kamcoback.postgres.core.LabelAllocateCoreService;
|
import com.kamco.cd.kamcoback.postgres.core.LabelAllocateCoreService;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -114,6 +116,36 @@ public class LabelAllocateService {
|
|||||||
return WorkerListResponse.builder().projectInfo(projectInfo).progressInfo(progressInfo).build();
|
return WorkerListResponse.builder().projectInfo(projectInfo).progressInfo(progressInfo).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 작업자 통계 조회 (UUID 기반)
|
||||||
|
*
|
||||||
|
* @param uuid 프로젝트 UUID (선택, 미입력 시 최신 프로젝트 조회)
|
||||||
|
* @param workerType 작업자 유형 (LABELER/INSPECTOR)
|
||||||
|
* @param search 검색어 (이름 또는 사번)
|
||||||
|
* @param sortType 정렬 조건
|
||||||
|
* @return 작업자 목록 및 통계
|
||||||
|
*/
|
||||||
|
public WorkerListResponse getWorkerStatisticsByUuid(
|
||||||
|
String uuid, String workerType, String search, String sortType) {
|
||||||
|
|
||||||
|
ProjectInfo projectInfo;
|
||||||
|
WorkProgressInfo progressInfo;
|
||||||
|
|
||||||
|
if (uuid != null && !uuid.isBlank()) {
|
||||||
|
// UUID로 프로젝트 정보 조회
|
||||||
|
projectInfo = labelAllocateCoreService.findProjectInfoByUuid(uuid);
|
||||||
|
// UUID로 작업 진행 현황 조회
|
||||||
|
progressInfo = labelAllocateCoreService.findWorkProgressInfoByUuid(uuid);
|
||||||
|
} else {
|
||||||
|
// 최신 프로젝트 정보 조회
|
||||||
|
projectInfo = labelAllocateCoreService.findLatestProjectInfo();
|
||||||
|
// 최신 프로젝트 작업 진행 현황 조회
|
||||||
|
progressInfo = labelAllocateCoreService.findWorkProgressInfo(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
return WorkerListResponse.builder().projectInfo(projectInfo).progressInfo(progressInfo).build();
|
||||||
|
}
|
||||||
|
|
||||||
public InferenceDetail findInferenceDetail(String uuid) {
|
public InferenceDetail findInferenceDetail(String uuid) {
|
||||||
return labelAllocateCoreService.findInferenceDetail(uuid);
|
return labelAllocateCoreService.findInferenceDetail(uuid);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,6 +61,10 @@ public class LabelAllocateCoreService {
|
|||||||
return labelAllocateRepository.findLatestProjectInfo();
|
return labelAllocateRepository.findLatestProjectInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ProjectInfo findProjectInfoByUuid(String uuid) {
|
||||||
|
return labelAllocateRepository.findProjectInfoByUuid(uuid);
|
||||||
|
}
|
||||||
|
|
||||||
public UUID findLastLabelWorkState() {
|
public UUID findLastLabelWorkState() {
|
||||||
return labelAllocateRepository.findLastLabelWorkState();
|
return labelAllocateRepository.findLastLabelWorkState();
|
||||||
}
|
}
|
||||||
@@ -74,6 +78,10 @@ public class LabelAllocateCoreService {
|
|||||||
return labelAllocateRepository.findWorkProgressInfo(analUid);
|
return labelAllocateRepository.findWorkProgressInfo(analUid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public WorkProgressInfo findWorkProgressInfoByUuid(String uuid) {
|
||||||
|
return labelAllocateRepository.findWorkProgressInfoByUuid(uuid);
|
||||||
|
}
|
||||||
|
|
||||||
public Long findDailyProcessedCount(
|
public Long findDailyProcessedCount(
|
||||||
String workerId, String workerType, LocalDate date, Long analUid) {
|
String workerId, String workerType, LocalDate date, Long analUid) {
|
||||||
return labelAllocateRepository.findDailyProcessedCount(workerId, workerType, date, analUid);
|
return labelAllocateRepository.findDailyProcessedCount(workerId, workerType, date, analUid);
|
||||||
|
|||||||
@@ -37,6 +37,9 @@ public interface LabelAllocateRepositoryCustom {
|
|||||||
// 최신 프로젝트 정보 조회 (analUid 없이)
|
// 최신 프로젝트 정보 조회 (analUid 없이)
|
||||||
ProjectInfo findLatestProjectInfo();
|
ProjectInfo findLatestProjectInfo();
|
||||||
|
|
||||||
|
// UUID로 프로젝트 정보 조회
|
||||||
|
ProjectInfo findProjectInfoByUuid(String uuid);
|
||||||
|
|
||||||
// 최신 작업 상태의 UUID 조회
|
// 최신 작업 상태의 UUID 조회
|
||||||
UUID findLastLabelWorkState();
|
UUID findLastLabelWorkState();
|
||||||
|
|
||||||
@@ -47,6 +50,9 @@ public interface LabelAllocateRepositoryCustom {
|
|||||||
// 작업 진행 현황 조회
|
// 작업 진행 현황 조회
|
||||||
WorkProgressInfo findWorkProgressInfo(Long analUid);
|
WorkProgressInfo findWorkProgressInfo(Long analUid);
|
||||||
|
|
||||||
|
// UUID로 작업 진행 현황 조회
|
||||||
|
WorkProgressInfo findWorkProgressInfoByUuid(String uuid);
|
||||||
|
|
||||||
// 작업자별 일일 처리량 조회
|
// 작업자별 일일 처리량 조회
|
||||||
Long findDailyProcessedCount(String workerId, String workerType, LocalDate date, Long analUid);
|
Long findDailyProcessedCount(String workerId, String workerType, LocalDate date, Long analUid);
|
||||||
|
|
||||||
|
|||||||
@@ -496,6 +496,154 @@ public class LabelAllocateRepositoryImpl implements LabelAllocateRepositoryCusto
|
|||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public WorkProgressInfo findWorkProgressInfoByUuid(String uuid) {
|
||||||
|
if (uuid == null || uuid.isBlank()) {
|
||||||
|
return findWorkProgressInfo(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
UUID targetUuid = UUID.fromString(uuid);
|
||||||
|
|
||||||
|
// UUID로 analUid 조회
|
||||||
|
Long effectiveAnalUid =
|
||||||
|
queryFactory
|
||||||
|
.select(mapSheetAnalInferenceEntity.id)
|
||||||
|
.from(mapSheetAnalInferenceEntity)
|
||||||
|
.where(mapSheetAnalInferenceEntity.uuid.eq(targetUuid))
|
||||||
|
.fetchOne();
|
||||||
|
|
||||||
|
if (effectiveAnalUid == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
BooleanExpression analUidCondition = labelingAssignmentEntity.analUid.eq(effectiveAnalUid);
|
||||||
|
|
||||||
|
// analUid로 분석 정보(compareYyyy, targetYyyy, stage) 조회
|
||||||
|
MapSheetAnalInferenceEntity analEntity =
|
||||||
|
queryFactory
|
||||||
|
.selectFrom(mapSheetAnalInferenceEntity)
|
||||||
|
.where(mapSheetAnalInferenceEntity.id.eq(effectiveAnalUid))
|
||||||
|
.fetchOne();
|
||||||
|
|
||||||
|
// 라벨링 대상 건수: tb_map_sheet_anal_data_inference_geom에서 pnu > 0 AND pass_yn = false(부적합)인 건수
|
||||||
|
Long labelingTargetCount = 0L;
|
||||||
|
if (analEntity != null) {
|
||||||
|
labelingTargetCount =
|
||||||
|
queryFactory
|
||||||
|
.select(mapSheetAnalDataInferenceGeomEntity.geoUid.count())
|
||||||
|
.from(mapSheetAnalDataInferenceGeomEntity)
|
||||||
|
.where(
|
||||||
|
mapSheetAnalDataInferenceGeomEntity.compareYyyy.eq(analEntity.getCompareYyyy()),
|
||||||
|
mapSheetAnalDataInferenceGeomEntity.targetYyyy.eq(analEntity.getTargetYyyy()),
|
||||||
|
mapSheetAnalDataInferenceGeomEntity.stage.eq(analEntity.getStage()),
|
||||||
|
mapSheetAnalDataInferenceGeomEntity.pnu.gt(0L),
|
||||||
|
mapSheetAnalDataInferenceGeomEntity.passYn.isFalse())
|
||||||
|
.fetchOne();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 전체 배정 건수 (tb_labeling_assignment 기준)
|
||||||
|
Long totalAssigned =
|
||||||
|
queryFactory
|
||||||
|
.select(labelingAssignmentEntity.count())
|
||||||
|
.from(labelingAssignmentEntity)
|
||||||
|
.where(analUidCondition)
|
||||||
|
.fetchOne();
|
||||||
|
|
||||||
|
// === 라벨링 통계 ===
|
||||||
|
Long labelingCompleted =
|
||||||
|
queryFactory
|
||||||
|
.select(labelingAssignmentEntity.count())
|
||||||
|
.from(labelingAssignmentEntity)
|
||||||
|
.where(
|
||||||
|
analUidCondition,
|
||||||
|
labelingAssignmentEntity.workState.in("LABEL_FIN", "TEST_ING", "DONE"))
|
||||||
|
.fetchOne();
|
||||||
|
|
||||||
|
Long skipCount =
|
||||||
|
queryFactory
|
||||||
|
.select(labelingAssignmentEntity.count())
|
||||||
|
.from(labelingAssignmentEntity)
|
||||||
|
.where(analUidCondition, labelingAssignmentEntity.workState.eq("SKIP"))
|
||||||
|
.fetchOne();
|
||||||
|
|
||||||
|
Long labelerCount =
|
||||||
|
queryFactory
|
||||||
|
.select(labelingAssignmentEntity.workerUid.countDistinct())
|
||||||
|
.from(labelingAssignmentEntity)
|
||||||
|
.where(analUidCondition, labelingAssignmentEntity.workerUid.isNotNull())
|
||||||
|
.fetchOne();
|
||||||
|
|
||||||
|
// === 검수 통계 ===
|
||||||
|
Long inspectionCompleted =
|
||||||
|
queryFactory
|
||||||
|
.select(labelingAssignmentEntity.count())
|
||||||
|
.from(labelingAssignmentEntity)
|
||||||
|
.where(analUidCondition, labelingAssignmentEntity.workState.eq("DONE"))
|
||||||
|
.fetchOne();
|
||||||
|
|
||||||
|
Long inspectorCount =
|
||||||
|
queryFactory
|
||||||
|
.select(labelingAssignmentEntity.inspectorUid.countDistinct())
|
||||||
|
.from(labelingAssignmentEntity)
|
||||||
|
.where(analUidCondition, labelingAssignmentEntity.inspectorUid.isNotNull())
|
||||||
|
.fetchOne();
|
||||||
|
|
||||||
|
// 계산
|
||||||
|
long labelingTotal = labelingTargetCount != null ? labelingTargetCount : 0L;
|
||||||
|
long labelCompleted = labelingCompleted != null ? labelingCompleted : 0L;
|
||||||
|
long inspectCompleted = inspectionCompleted != null ? inspectionCompleted : 0L;
|
||||||
|
long skipped = skipCount != null ? skipCount : 0L;
|
||||||
|
|
||||||
|
long labelingRemaining = labelingTotal - labelCompleted - skipped;
|
||||||
|
if (labelingRemaining < 0) labelingRemaining = 0;
|
||||||
|
|
||||||
|
long inspectionTotal = labelingTotal;
|
||||||
|
long inspectionRemaining = inspectionTotal - inspectCompleted - skipped;
|
||||||
|
if (inspectionRemaining < 0) inspectionRemaining = 0;
|
||||||
|
|
||||||
|
double labelingRate = labelingTotal > 0 ? (double) labelCompleted / labelingTotal * 100 : 0.0;
|
||||||
|
double inspectionRate =
|
||||||
|
inspectionTotal > 0 ? (double) inspectCompleted / inspectionTotal * 100 : 0.0;
|
||||||
|
|
||||||
|
// 상태 판단
|
||||||
|
String labelingStatus;
|
||||||
|
String inspectionStatus;
|
||||||
|
|
||||||
|
if (analEntity != null && "Y".equals(analEntity.getLabelingClosedYn())) {
|
||||||
|
labelingStatus = "종료";
|
||||||
|
} else {
|
||||||
|
labelingStatus = labelingRemaining > 0 ? "진행중" : "완료";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (analEntity != null && "Y".equals(analEntity.getInspectionClosedYn())) {
|
||||||
|
inspectionStatus = "종료";
|
||||||
|
} else {
|
||||||
|
inspectionStatus = inspectionRemaining > 0 ? "진행중" : "완료";
|
||||||
|
}
|
||||||
|
|
||||||
|
return WorkProgressInfo.builder()
|
||||||
|
.labelingProgressRate(labelingRate)
|
||||||
|
.labelingStatus(labelingStatus)
|
||||||
|
.labelingTotalCount(labelingTotal)
|
||||||
|
.labelingCompletedCount(labelCompleted)
|
||||||
|
.labelingSkipCount(skipped)
|
||||||
|
.labelingRemainingCount(labelingRemaining)
|
||||||
|
.labelerCount(labelerCount != null ? labelerCount : 0L)
|
||||||
|
.inspectionProgressRate(inspectionRate)
|
||||||
|
.inspectionStatus(inspectionStatus)
|
||||||
|
.inspectionTotalCount(inspectionTotal)
|
||||||
|
.inspectionCompletedCount(inspectCompleted)
|
||||||
|
.inspectionSkipCount(skipped)
|
||||||
|
.inspectionRemainingCount(inspectionRemaining)
|
||||||
|
.inspectorCount(inspectorCount != null ? inspectorCount : 0L)
|
||||||
|
.progressRate(labelingRate)
|
||||||
|
.totalAssignedCount(labelingTotal)
|
||||||
|
.completedCount(labelCompleted)
|
||||||
|
.remainingLabelCount(labelingRemaining)
|
||||||
|
.remainingInspectCount(inspectionRemaining)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Long findDailyProcessedCount(
|
public Long findDailyProcessedCount(
|
||||||
String workerId, String workerType, LocalDate date, Long analUid) {
|
String workerId, String workerType, LocalDate date, Long analUid) {
|
||||||
@@ -832,6 +980,56 @@ public class LabelAllocateRepositoryImpl implements LabelAllocateRepositoryCusto
|
|||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ProjectInfo findProjectInfoByUuid(String uuid) {
|
||||||
|
if (uuid == null || uuid.isBlank()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
UUID targetUuid = UUID.fromString(uuid);
|
||||||
|
|
||||||
|
var result =
|
||||||
|
queryFactory
|
||||||
|
.select(
|
||||||
|
mapSheetAnalInferenceEntity.compareYyyy,
|
||||||
|
mapSheetAnalInferenceEntity.targetYyyy,
|
||||||
|
mapSheetAnalInferenceEntity.stage,
|
||||||
|
mapSheetAnalInferenceEntity.gukyuinApplyDttm,
|
||||||
|
mapSheetAnalInferenceEntity.createdDttm,
|
||||||
|
mapSheetAnalInferenceEntity.uuid,
|
||||||
|
mapSheetAnalInferenceEntity.labelingClosedYn,
|
||||||
|
mapSheetAnalInferenceEntity.inspectionClosedYn)
|
||||||
|
.from(mapSheetAnalInferenceEntity)
|
||||||
|
.where(mapSheetAnalInferenceEntity.uuid.eq(targetUuid))
|
||||||
|
.fetchOne();
|
||||||
|
|
||||||
|
if (result == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Integer compareYyyy = result.get(mapSheetAnalInferenceEntity.compareYyyy);
|
||||||
|
Integer targetYyyy = result.get(mapSheetAnalInferenceEntity.targetYyyy);
|
||||||
|
Integer stage = result.get(mapSheetAnalInferenceEntity.stage);
|
||||||
|
ZonedDateTime gukyuinApplyDttm = result.get(mapSheetAnalInferenceEntity.gukyuinApplyDttm);
|
||||||
|
ZonedDateTime createdDttm = result.get(mapSheetAnalInferenceEntity.createdDttm);
|
||||||
|
String labelingClosedYn = result.get(mapSheetAnalInferenceEntity.labelingClosedYn);
|
||||||
|
String inspectionClosedYn = result.get(mapSheetAnalInferenceEntity.inspectionClosedYn);
|
||||||
|
|
||||||
|
String detectionYear =
|
||||||
|
(compareYyyy != null && targetYyyy != null) ? compareYyyy + "-" + targetYyyy : null;
|
||||||
|
String round = stage != null ? String.valueOf(stage) : null;
|
||||||
|
|
||||||
|
return ProjectInfo.builder()
|
||||||
|
.detectionYear(detectionYear)
|
||||||
|
.stage(round)
|
||||||
|
.gukyuinApplyDttm(gukyuinApplyDttm)
|
||||||
|
.startDttm(createdDttm)
|
||||||
|
.uuid(uuid)
|
||||||
|
.labelingClosedYn(labelingClosedYn)
|
||||||
|
.inspectionClosedYn(inspectionClosedYn)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UUID findLastLabelWorkState() {
|
public UUID findLastLabelWorkState() {
|
||||||
BooleanBuilder whereBuilder = new BooleanBuilder();
|
BooleanBuilder whereBuilder = new BooleanBuilder();
|
||||||
|
|||||||
Reference in New Issue
Block a user