From 96f5a87b1a7173288f9625c18b8e393c7a9d7e6e Mon Sep 17 00:00:00 2001 From: DanielLee <198891672+sanghyeonhd@users.noreply.github.com> Date: Mon, 5 Jan 2026 12:33:48 +0900 Subject: [PATCH 1/5] =?UTF-8?q?=EC=9E=91=EC=97=85=ED=98=84=ED=99=A9?= =?UTF-8?q?=EA=B4=80=EB=A6=AC=20=EB=8D=B0=EC=9D=B4=ED=84=B0=20=EB=B0=98?= =?UTF-8?q?=ED=99=98=EA=B0=92=20=EC=B6=94=EA=B0=80=EC=A4=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../label/LabelAllocateApiController.java | 2 + .../kamcoback/label/dto/WorkerStatsDto.java | 87 +++++++++++++++++-- .../label/LabelAllocateRepositoryImpl.java | 6 ++ 3 files changed, 86 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 1395f42b..4e0f9373 100644 --- a/src/main/java/com/kamco/cd/kamcoback/label/LabelAllocateApiController.java +++ b/src/main/java/com/kamco/cd/kamcoback/label/LabelAllocateApiController.java @@ -85,6 +85,8 @@ public class LabelAllocateApiController { allowableValues = { "REMAINING_DESC", "REMAINING_ASC", + "COMPLETED_DESC", + "COMPLETED_ASC", "NAME_ASC", "NAME_DESC" }, diff --git a/src/main/java/com/kamco/cd/kamcoback/label/dto/WorkerStatsDto.java b/src/main/java/com/kamco/cd/kamcoback/label/dto/WorkerStatsDto.java index f879f0ee..e95dd346 100644 --- a/src/main/java/com/kamco/cd/kamcoback/label/dto/WorkerStatsDto.java +++ b/src/main/java/com/kamco/cd/kamcoback/label/dto/WorkerStatsDto.java @@ -10,6 +10,27 @@ import lombok.Setter; public class WorkerStatsDto { + @Getter + @Setter + @Builder + @NoArgsConstructor + @AllArgsConstructor + @Schema(description = "프로젝트 기본 정보 (상단 표시용)") + public static class ProjectInfo { + + @Schema(description = "변화탐지년도 (예: 2026-2025)") + private String detectionYear; + + @Schema(description = "회차 (예: 8)") + private String round; + + @Schema(description = "국유인 반영일 (예: 2026-03-31)") + private String reflectionDate; + + @Schema(description = "작업 시작일 (예: 2026-04-06)") + private String startDate; + } + @Getter @Setter @Builder @@ -75,29 +96,74 @@ public class WorkerStatsDto { @Schema(description = "작업 진행 현황 정보") public static class WorkProgressInfo { + // === 라벨링 관련 === @Schema(description = "라벨링 진행률 (완료건+스킵건)/배정건") private Double labelingProgressRate; - @Schema(description = "작업 상태 (진행중/종료)") - private String workStatus; + @Schema(description = "라벨링 작업 상태 (진행중/완료)") + private String labelingStatus; - @Schema(description = "진행률 수치 (완료+스킵)") - private Long completedCount; + @Schema(description = "라벨링 전체 배정 건수") + private Long labelingTotalCount; - @Schema(description = "전체 배정 건수") - private Long totalAssignedCount; + @Schema(description = "라벨링 완료 건수 (LABEL_FIN + TEST_ING + DONE)") + private Long labelingCompletedCount; + + @Schema(description = "라벨링 스킵 건수 (SKIP)") + private Long labelingSkipCount; + + @Schema(description = "라벨링 남은 작업 건수") + private Long labelingRemainingCount; @Schema(description = "투입된 라벨러 수") private Long labelerCount; - @Schema(description = "남은 라벨링 작업 데이터 수") - private Long remainingLabelCount; + // === 검수(Inspection) 관련 (신규 추가) === + @Schema(description = "검수 진행률 (완료건/대상건)") + private Double inspectionProgressRate; + + @Schema(description = "검수 작업 상태 (진행중/완료)") + private String inspectionStatus; + + @Schema(description = "검수 전체 대상 건수") + private Long inspectionTotalCount; + + @Schema(description = "검수 완료 건수 (DONE)") + private Long inspectionCompletedCount; + + @Schema(description = "검수 제외 건수 (라벨링 스킵과 동일)") + private Long inspectionSkipCount; + + @Schema(description = "검수 남은 작업 건수") + private Long inspectionRemainingCount; @Schema(description = "투입된 검수자 수") private Long inspectorCount; - @Schema(description = "남은 검수 작업 데이터 수") + // === 레거시 호환 필드 (Deprecated) === + @Deprecated + @Schema(description = "[Deprecated] labelingProgressRate 사용 권장") + private Double progressRate; + + @Deprecated + @Schema(description = "[Deprecated] labelingTotalCount 사용 권장") + private Long totalAssignedCount; + + @Deprecated + @Schema(description = "[Deprecated] labelingCompletedCount 사용 권장") + private Long completedCount; + + @Deprecated + @Schema(description = "[Deprecated] labelingRemainingCount 사용 권장") + private Long remainingLabelCount; + + @Deprecated + @Schema(description = "[Deprecated] inspectionRemainingCount 사용 권장") private Long remainingInspectCount; + + @Deprecated + @Schema(description = "[Deprecated] labelingStatus/inspectionStatus 사용 권장") + private String workStatus; } @Getter @@ -108,6 +174,9 @@ public class WorkerStatsDto { @Schema(description = "작업자 목록 응답 (작업 정보 포함)") public static class WorkerListResponse { + @Schema(description = "프로젝트 기본 정보 (상단 표시용)") + private ProjectInfo projectInfo; + @Schema(description = "작업 진행 현황 정보") private WorkProgressInfo progressInfo; 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 6d973dad..d6ceeb0f 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 @@ -268,6 +268,12 @@ public class LabelAllocateRepositoryImpl implements LabelAllocateRepositoryCusto case "REMAINING_ASC": baseQuery.orderBy(remainingSum.asc()); break; + case "COMPLETED_DESC": + baseQuery.orderBy(completedSum.desc()); + break; + case "COMPLETED_ASC": + baseQuery.orderBy(completedSum.asc()); + break; case "NAME_ASC": baseQuery.orderBy(memberEntity.name.asc()); break; From 040aabe95e252f25d11b693555e4cf1df89f8218 Mon Sep 17 00:00:00 2001 From: Moon Date: Mon, 5 Jan 2026 12:41:07 +0900 Subject: [PATCH 2/5] =?UTF-8?q?=EC=9E=91=EC=97=85=ED=98=84=ED=99=A9=20DTO?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kamcoback/label/dto/WorkerStatsDto.java | 40 ++++++------------- 1 file changed, 13 insertions(+), 27 deletions(-) diff --git a/src/main/java/com/kamco/cd/kamcoback/label/dto/WorkerStatsDto.java b/src/main/java/com/kamco/cd/kamcoback/label/dto/WorkerStatsDto.java index efca81b2..6df63cf0 100644 --- a/src/main/java/com/kamco/cd/kamcoback/label/dto/WorkerStatsDto.java +++ b/src/main/java/com/kamco/cd/kamcoback/label/dto/WorkerStatsDto.java @@ -31,42 +31,28 @@ public class WorkerStatsDto { private Long totalAssigned; @Schema(description = "완료 건수") - private Long completed; + private Long doneCnt; @Schema(description = "스킵 건수") - private Long skipped; + private Long skipCnt; @Schema(description = "남은 작업 건수") - private Long remaining; - - @Schema(description = "최근 3일간 처리 이력") - private DailyHistory history; - - @Schema(description = "작업 정체 여부 (3일간 실적이 저조하면 true)") - private Boolean isStagnated; - } - - @Getter - @Setter - @Builder - @NoArgsConstructor - @AllArgsConstructor - @Schema(description = "최근 3일간 일일 처리 이력") - public static class DailyHistory { - - @Schema(description = "1일 전 (어제) 처리량") - private Long day1Ago; - - @Schema(description = "2일 전 처리량") - private Long day2Ago; + private Long remainingCnt; @Schema(description = "3일 전 처리량") - private Long day3Ago; + private Long day3AgoDoneCnt; - @Schema(description = "3일 평균 처리량") - private Long average; + @Schema(description = "2일 전 처리량") + private Long day2AgoDoneCnt; + + @Schema(description = "1일 전 처리량") + private Long day1AgoDoneCnt; + + //@Schema(description = "작업 정체 여부 (3일간 실적이 저조하면 true)") + //private Boolean isStagnated; } + @Getter @Setter @Builder From 06d4b597cb32fa8bfd9bef28378f38aae7d01d16 Mon Sep 17 00:00:00 2001 From: DanielLee <198891672+sanghyeonhd@users.noreply.github.com> Date: Mon, 5 Jan 2026 12:42:10 +0900 Subject: [PATCH 3/5] =?UTF-8?q?=EC=9E=91=EC=97=85=ED=98=84=ED=99=A9?= =?UTF-8?q?=EA=B4=80=EB=A6=AC=20Data=20accept=20fix?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../label/service/LabelAllocateService.java | 4 + .../core/LabelAllocateCoreService.java | 5 + .../label/LabelAllocateRepositoryCustom.java | 4 + .../label/LabelAllocateRepositoryImpl.java | 159 ++++++++++++++---- 4 files changed, 140 insertions(+), 32 deletions(-) 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 7da6156c..ae0ada1d 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 @@ -129,6 +129,9 @@ public class LabelAllocateService { Integer page, Integer size) { + // 프로젝트 정보 조회 (analUid가 있을 때만) + var projectInfo = labelAllocateCoreService.findProjectInfo(analUid); + // 작업 진행 현황 조회 var progressInfo = labelAllocateCoreService.findWorkProgressInfo(analUid); @@ -178,6 +181,7 @@ public class LabelAllocateService { (fromIndex < workers.size()) ? workers.subList(fromIndex, toIndex) : List.of(); return WorkerListResponse.builder() + .projectInfo(projectInfo) .progressInfo(progressInfo) .workers(pagedWorkers) .currentPage(page) 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 d71471c0..a16252fa 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.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.WorkerStatistics; import com.kamco.cd.kamcoback.postgres.entity.LabelingAssignmentEntity; @@ -48,6 +49,10 @@ public class LabelAllocateCoreService { return labelAllocateRepository.availUserList(role); } + public ProjectInfo findProjectInfo(Long analUid) { + return labelAllocateRepository.findProjectInfo(analUid); + } + public List findWorkerStatistics( Long analUid, String workerType, 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 a127e142..739c30c2 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 @@ -4,6 +4,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.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.WorkerStatistics; import com.kamco.cd.kamcoback.postgres.entity.LabelingAssignmentEntity; @@ -26,6 +27,9 @@ public interface LabelAllocateRepositoryCustom { List availUserList(String role); + // 프로젝트 정보 조회 + ProjectInfo findProjectInfo(Long analUid); + // 작업자 통계 조회 List findWorkerStatistics( Long analUid, String workerType, String search, String sortType); 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 d6ceeb0f..141bace8 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.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.WorkerStatistics; import com.kamco.cd.kamcoback.postgres.entity.LabelingAssignmentEntity; @@ -34,9 +35,12 @@ import java.time.LocalDate; import java.time.LocalTime; import java.time.ZoneId; import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; import java.util.List; import java.util.Objects; import java.util.UUID; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Repository; @@ -319,17 +323,28 @@ public class LabelAllocateRepositoryImpl implements LabelAllocateRepositoryCusto .where(analUidCondition) .fetchOne(); - // 완료 + 스킵 건수 - Long completedCount = + // === 라벨링 통계 === + // 라벨링 완료: LABEL_FIN, TEST_ING, DONE (검수 포함) + Long labelingCompleted = queryFactory .select(labelingAssignmentEntity.count()) .from(labelingAssignmentEntity) .where( analUidCondition, - labelingAssignmentEntity.workState.in("DONE", "SKIP")) + labelingAssignmentEntity.workState.in("LABEL_FIN", "TEST_ING", "DONE")) .fetchOne(); - // 투입된 라벨러 수 (고유한 worker_uid 수) + // 스킵 건수 + Long skipCount = + queryFactory + .select(labelingAssignmentEntity.count()) + .from(labelingAssignmentEntity) + .where( + analUidCondition, + labelingAssignmentEntity.workState.eq("SKIP")) + .fetchOne(); + + // 투입된 라벨러 수 Long labelerCount = queryFactory .select(labelingAssignmentEntity.workerUid.countDistinct()) @@ -339,18 +354,18 @@ public class LabelAllocateRepositoryImpl implements LabelAllocateRepositoryCusto labelingAssignmentEntity.workerUid.isNotNull()) .fetchOne(); - // 남은 라벨링 작업 데이터 수 - Long remainingLabelCount = + // === 검수 통계 === + // 검수 완료: DONE만 + Long inspectionCompleted = queryFactory .select(labelingAssignmentEntity.count()) .from(labelingAssignmentEntity) .where( analUidCondition, - labelingAssignmentEntity.workerUid.isNotNull(), - labelingAssignmentEntity.workState.notIn("DONE", "SKIP")) + labelingAssignmentEntity.workState.eq("DONE")) .fetchOne(); - // 투입된 검수자 수 (고유한 inspector_uid 수) + // 투입된 검수자 수 Long inspectorCount = queryFactory .select(labelingAssignmentEntity.inspectorUid.countDistinct()) @@ -360,36 +375,47 @@ public class LabelAllocateRepositoryImpl implements LabelAllocateRepositoryCusto labelingAssignmentEntity.inspectorUid.isNotNull()) .fetchOne(); - // 남은 검수 작업 데이터 수 - Long remainingInspectCount = - queryFactory - .select(labelingAssignmentEntity.count()) - .from(labelingAssignmentEntity) - .where( - analUidCondition, - labelingAssignmentEntity.inspectorUid.isNotNull(), - labelingAssignmentEntity.workState.notIn("DONE")) - .fetchOne(); + // 남은 작업 건수 계산 + long total = totalAssigned != null ? totalAssigned : 0L; + long labelCompleted = labelingCompleted != null ? labelingCompleted : 0L; + long inspectCompleted = inspectionCompleted != null ? inspectionCompleted : 0L; + long skipped = skipCount != null ? skipCount : 0L; + + long labelingRemaining = total - labelCompleted - skipped; + long inspectionRemaining = total - inspectCompleted - skipped; // 진행률 계산 - double progressRate = 0.0; - if (totalAssigned != null && totalAssigned > 0) { - progressRate = - (completedCount != null ? completedCount.doubleValue() : 0.0) / totalAssigned * 100; - } + double labelingRate = total > 0 ? (double) labelCompleted / total * 100 : 0.0; + double inspectionRate = total > 0 ? (double) inspectCompleted / total * 100 : 0.0; - // 작업 상태 판단 (간단하게 진행률 100%면 종료, 아니면 진행중) - String workStatus = (progressRate >= 100.0) ? "종료" : "진행중"; + // 상태 판단 + String labelingStatus = labelingRemaining > 0 ? "진행중" : "완료"; + String inspectionStatus = inspectionRemaining > 0 ? "진행중" : "완료"; return WorkProgressInfo.builder() - .labelingProgressRate(progressRate) - .workStatus(workStatus) - .completedCount(completedCount != null ? completedCount : 0L) - .totalAssignedCount(totalAssigned != null ? totalAssigned : 0L) + // 라벨링 + .labelingProgressRate(labelingRate) + .labelingStatus(labelingStatus) + .labelingTotalCount(total) + .labelingCompletedCount(labelCompleted) + .labelingSkipCount(skipped) + .labelingRemainingCount(labelingRemaining) .labelerCount(labelerCount != null ? labelerCount : 0L) - .remainingLabelCount(remainingLabelCount != null ? remainingLabelCount : 0L) + // 검수 + .inspectionProgressRate(inspectionRate) + .inspectionStatus(inspectionStatus) + .inspectionTotalCount(total) + .inspectionCompletedCount(inspectCompleted) + .inspectionSkipCount(skipped) + .inspectionRemainingCount(inspectionRemaining) .inspectorCount(inspectorCount != null ? inspectorCount : 0L) - .remainingInspectCount(remainingInspectCount != null ? remainingInspectCount : 0L) + // 레거시 호환 필드 (Deprecated) + .progressRate(labelingRate) + .totalAssignedCount(total) + .completedCount(labelCompleted) + .remainingLabelCount(labelingRemaining) + .remainingInspectCount(inspectionRemaining) + .workStatus(labelingStatus) .build(); } @@ -600,4 +626,73 @@ public class LabelAllocateRepositoryImpl implements LabelAllocateRepositoryCusto em.flush(); em.clear(); } + + @Override + public ProjectInfo findProjectInfo(Long analUid) { + if (analUid == null) { + return null; + } + + var result = queryFactory + .select( + mapSheetAnalEntity.compareYyyy, + mapSheetAnalEntity.targetYyyy, + mapSheetAnalEntity.analTitle, + mapSheetAnalEntity.gukyuinApplyDttm, + mapSheetAnalEntity.analStrtDttm + ) + .from(mapSheetAnalEntity) + .where(mapSheetAnalEntity.id.eq(analUid)) + .fetchOne(); + + if (result == null) { + return null; + } + + Integer compareYyyy = result.get(mapSheetAnalEntity.compareYyyy); + Integer targetYyyy = result.get(mapSheetAnalEntity.targetYyyy); + String analTitle = result.get(mapSheetAnalEntity.analTitle); + ZonedDateTime gukyuinApplyDttm = result.get(mapSheetAnalEntity.gukyuinApplyDttm); + ZonedDateTime analStrtDttm = result.get(mapSheetAnalEntity.analStrtDttm); + + // 변화탐지년도 생성 + String detectionYear = (compareYyyy != null && targetYyyy != null) + ? compareYyyy + "-" + targetYyyy + : null; + + // 회차 추출 (예: "8회차" → "8") + String round = extractRoundFromTitle(analTitle); + + return ProjectInfo.builder() + .detectionYear(detectionYear) + .round(round) + .reflectionDate(formatDate(gukyuinApplyDttm)) + .startDate(formatDate(analStrtDttm)) + .build(); + } + + /** + * 제목에서 회차 숫자 추출 + * 예: "8회차", "제8회차" → "8" + */ + private String extractRoundFromTitle(String title) { + if (title == null || title.isEmpty()) { + return null; + } + + Pattern pattern = Pattern.compile("(\\d+)회차"); + Matcher matcher = pattern.matcher(title); + + return matcher.find() ? matcher.group(1) : null; + } + + /** + * ZonedDateTime을 "yyyy-MM-dd" 형식으로 변환 + */ + private String formatDate(ZonedDateTime dateTime) { + if (dateTime == null) { + return null; + } + return dateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")); + } } From ba0e408c2b7e1d1fe4feaecb893374999c234020 Mon Sep 17 00:00:00 2001 From: DanielLee <198891672+sanghyeonhd@users.noreply.github.com> Date: Mon, 5 Jan 2026 12:45:50 +0900 Subject: [PATCH 4/5] Build Error Fix --- .../kamcoback/label/dto/WorkerStatsDto.java | 54 +++++++++++++++---- 1 file changed, 44 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/kamco/cd/kamcoback/label/dto/WorkerStatsDto.java b/src/main/java/com/kamco/cd/kamcoback/label/dto/WorkerStatsDto.java index 581aac7e..3501da8a 100644 --- a/src/main/java/com/kamco/cd/kamcoback/label/dto/WorkerStatsDto.java +++ b/src/main/java/com/kamco/cd/kamcoback/label/dto/WorkerStatsDto.java @@ -52,25 +52,59 @@ public class WorkerStatsDto { private Long totalAssigned; @Schema(description = "완료 건수") - private Long doneCnt; + private Long completed; @Schema(description = "스킵 건수") - private Long skipCnt; + private Long skipped; @Schema(description = "남은 작업 건수") - private Long remainingCnt; + private Long remaining; - @Schema(description = "3일 전 처리량") - private Long day3AgoDoneCnt; + @Schema(description = "최근 3일간 처리 이력") + private DailyHistory history; + + @Schema(description = "작업 정체 여부 (3일간 실적이 저조하면 true)") + private Boolean isStagnated; + + // 레거시 필드 (기존 호환성 유지) + @Deprecated + private Long doneCnt; // completed로 대체 + + @Deprecated + private Long skipCnt; // skipped로 대체 + + @Deprecated + private Long remainingCnt; // remaining으로 대체 + + @Deprecated + private Long day3AgoDoneCnt; // history.day3Ago로 대체 + + @Deprecated + private Long day2AgoDoneCnt; // history.day2Ago로 대체 + + @Deprecated + private Long day1AgoDoneCnt; // history.day1Ago로 대체 + } + + @Getter + @Setter + @Builder + @NoArgsConstructor + @AllArgsConstructor + @Schema(description = "최근 3일간 일일 처리 이력") + public static class DailyHistory { + + @Schema(description = "1일 전 (어제) 처리량") + private Long day1Ago; @Schema(description = "2일 전 처리량") - private Long day2AgoDoneCnt; + private Long day2Ago; - @Schema(description = "1일 전 처리량") - private Long day1AgoDoneCnt; + @Schema(description = "3일 전 처리량") + private Long day3Ago; - //@Schema(description = "작업 정체 여부 (3일간 실적이 저조하면 true)") - //private Boolean isStagnated; + @Schema(description = "3일 평균 처리량") + private Long average; } From 877de7f17e176353fbc149fc1f7cb5df3579ea4f Mon Sep 17 00:00:00 2001 From: DanielLee <198891672+sanghyeonhd@users.noreply.github.com> Date: Mon, 5 Jan 2026 12:59:21 +0900 Subject: [PATCH 5/5] =?UTF-8?q?=EC=A3=BC=EC=84=9D=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cd/kamcoback/label/LabelAllocateApiController.java | 6 +++--- 1 file changed, 3 insertions(+), 3 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 4e0f9373..cb723a69 100644 --- a/src/main/java/com/kamco/cd/kamcoback/label/LabelAllocateApiController.java +++ b/src/main/java/com/kamco/cd/kamcoback/label/LabelAllocateApiController.java @@ -63,8 +63,8 @@ public class LabelAllocateApiController { }) @GetMapping("/admin/workers") public ApiResponseDto getWorkerStatistics( - @Parameter(description = "분석 ID (선택)", example = "3") @RequestParam(required = false) - Long analUid, + // @Parameter(description = "분석 ID (선택)", example = "3") @RequestParam(required = false) + // Long analUid, @Parameter( description = "작업자 유형 (선택) - 미입력 시 LABELER로 조회", example = "LABELER", @@ -105,7 +105,7 @@ public class LabelAllocateApiController { return ApiResponseDto.ok( labelAllocateService.getWorkerStatistics( - analUid, workerType, search, sort, page, size)); + null, workerType, search, sort, page, size)); } @Operation(summary = "라벨링작업 관리 > 작업 배정", description = "라벨링작업 관리 > 작업 배정")