From 91b09a917edebb9dbed0208e5779974c0138db96 Mon Sep 17 00:00:00 2001 From: "gayoun.park" Date: Wed, 14 Jan 2026 14:20:13 +0900 Subject: [PATCH] =?UTF-8?q?=ED=95=99=EC=8A=B5=EB=8D=B0=EC=9D=B4=ED=84=B0?= =?UTF-8?q?=EA=B4=80=EB=A6=AC=20>=20=EC=9E=91=EC=97=85=EC=9D=B4=EB=A0=A5?= =?UTF-8?q?=20=EC=A7=84=ED=96=89=EC=A4=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../label/LabelAllocateApiController.java | 18 +++ .../kamcoback/label/dto/LabelAllocateDto.java | 21 ++++ .../label/service/LabelAllocateService.java | 10 ++ .../core/LabelAllocateCoreService.java | 10 ++ .../label/LabelAllocateRepositoryCustom.java | 6 + .../label/LabelAllocateRepositoryImpl.java | 104 ++++++++++++++++++ 6 files changed, 169 insertions(+) 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 c5df481c..6745a735 100644 --- a/src/main/java/com/kamco/cd/kamcoback/label/LabelAllocateApiController.java +++ b/src/main/java/com/kamco/cd/kamcoback/label/LabelAllocateApiController.java @@ -5,6 +5,7 @@ import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto; 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.WorkHistoryDto; import com.kamco.cd.kamcoback.label.dto.WorkerStatsDto.UpdateClosedRequest; import com.kamco.cd.kamcoback.label.dto.WorkerStatsDto.WorkerListResponse; import com.kamco.cd.kamcoback.label.service.LabelAllocateService; @@ -302,4 +303,21 @@ public class LabelAllocateApiController { return ApiResponseDto.okObject( new ApiResponseDto.ResponseObj(ApiResponseDto.ApiResponseCode.OK, statusMessage)); } + + @Operation(summary = "라벨링작업 관리 > 상세 > 작업이력", description = "라벨링작업 관리 > 상세 > 작업이력") + @GetMapping("/work-history-list") + public ApiResponseDto> findWorkHistoryList( + @RequestParam(defaultValue = "0", required = true) int page, + @RequestParam(defaultValue = "20", required = true) int size, + @Parameter(description = "사번", required = true, example = "123456") @RequestParam + String userId, + @Schema( + allowableValues = {"LABELER", "REVIEWER"}, + defaultValue = "LABELER") + @Parameter(description = "라벨러/검수자(LABELER/REVIEWER)", required = true) + @RequestParam + String type) { + LabelAllocateDto.searchReq searchReq = new LabelAllocateDto.searchReq(page, size, ""); + return ApiResponseDto.ok(labelAllocateService.findWorkHistoryList(searchReq, userId, type)); + } } 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 a945e5f0..be15d446 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 @@ -314,4 +314,25 @@ public class LabelAllocateDto { private Long totalCnt; private List moveUserList; } + + @Schema(name = "WorkHistoryDto", description = "WorkHistoryDto") + @Getter + @Setter + @NoArgsConstructor + @AllArgsConstructor + public static class WorkHistoryDto { + + private Integer rowNum; + private String changeDetectionYear; + private Long stage; + private ZonedDateTime gukyuinApplyDttm; + private Long assignedCnt; + private Long completeCnt; + private Long skipCnt; + private Long remainCnt; + // private String status; + private Double percent; + private ZonedDateTime createdDttm; + private ZonedDateTime projectCloseDttm; + } } 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 e4fa63df..4a8b5502 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 @@ -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.TargetUser; import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.UserList; +import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.WorkHistoryDto; +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.WorkProgressInfo; import com.kamco.cd.kamcoback.label.dto.WorkerStatsDto.WorkerListResponse; @@ -250,4 +252,12 @@ public class LabelAllocateService { labelAllocateCoreService.updateClosedYnByUuid(targetUuid, closedType, closedYn); } + + public Page findWorkHistoryList(searchReq searchReq, String userId, String type) { + if (type.equals("LABELER")) { + return labelAllocateCoreService.workLabelHistoryList(searchReq, userId); + } else { + return labelAllocateCoreService.workReviewerHistoryList(searchReq, userId); + } + } } 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 86c165e9..fd6e985e 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 @@ -7,6 +7,7 @@ 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.MoveInfo; import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.UserList; +import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.WorkHistoryDto; 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.WorkProgressInfo; @@ -145,4 +146,13 @@ public class LabelAllocateCoreService { public void updateClosedYnByUuid(String uuid, String closedType, String closedYn) { labelAllocateRepository.updateClosedYnByUuid(uuid, closedType, closedYn); } + + public Page workLabelHistoryList( + LabelAllocateDto.searchReq searchReq, String userId) { + return labelAllocateRepository.workLabelHistoryList(searchReq, userId); + } + + public Page workReviewerHistoryList(searchReq searchReq, String userId) { + return labelAllocateRepository.workReviewerHistoryList(searchReq, userId); + } } 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 5980da85..a43df4e1 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 @@ -7,6 +7,8 @@ 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.MoveInfo; import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.UserList; +import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.WorkHistoryDto; +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.WorkProgressInfo; import com.kamco.cd.kamcoback.label.dto.WorkerStatsDto.WorkerStatistics; @@ -86,4 +88,8 @@ public interface LabelAllocateRepositoryCustom { // 프로젝트 종료 여부 업데이트 (uuid 기반) void updateClosedYnByUuid(String uuid, String closedType, String closedYn); + + Page workLabelHistoryList(LabelAllocateDto.searchReq searchReq, String userId); + + Page workReviewerHistoryList(searchReq searchReq, String userId); } 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 8bd68ed1..7d34b4de 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 @@ -18,6 +18,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.MoveUserList; import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.UserList; +import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.WorkHistoryDto; +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.WorkProgressInfo; import com.kamco.cd.kamcoback.label.dto.WorkerStatsDto.WorkerStatistics; @@ -32,6 +34,7 @@ import com.querydsl.core.types.dsl.CaseBuilder; import com.querydsl.core.types.dsl.Expressions; import com.querydsl.core.types.dsl.NumberExpression; import com.querydsl.core.types.dsl.StringExpression; +import com.querydsl.jpa.JPAExpressions; import com.querydsl.jpa.impl.JPAQueryFactory; import jakarta.persistence.EntityManager; import jakarta.persistence.EntityNotFoundException; @@ -1457,4 +1460,105 @@ public class LabelAllocateRepositoryImpl implements LabelAllocateRepositoryCusto em.flush(); em.clear(); } + + public Page workLabelHistoryList( + LabelAllocateDto.searchReq searchReq, String userId) { + + NumberExpression totalCnt = labelingAssignmentEntity.assignmentUid.count(); + + NumberExpression assignedCnt = + new CaseBuilder() + .when(labelingAssignmentEntity.workState.eq(LabelState.ASSIGNED.getId())) + .then(1L) + .otherwise((Long) null) + .count(); + + NumberExpression skipCnt = + new CaseBuilder() + .when(labelingAssignmentEntity.workState.eq(LabelState.SKIP.getId())) + .then(1L) + .otherwise((Long) null) + .count(); + + NumberExpression completeCnt = + new CaseBuilder() + .when(labelingAssignmentEntity.workState.eq(LabelState.DONE.getId())) + .then(1L) + .otherwise((Long) null) + .count(); + + NumberExpression percent = + new CaseBuilder() + .when(completeCnt.eq(0L)) + .then(0.0) + .otherwise( + Expressions.numberTemplate( + Double.class, + "round({0} / {1}, 2)", + completeCnt, + labelingAssignmentEntity.count())); + + Pageable pageable = searchReq.toPageable(); + List list = + queryFactory + .select( + Projections.constructor( + WorkHistoryDto.class, + Expressions.numberTemplate( + Integer.class, + "row_number() over(order by {0} desc)", + labelingAssignmentEntity.analUid), + Expressions.stringTemplate( + "concat({0}, '-', {1})", + mapSheetAnalInferenceEntity.compareYyyy, + mapSheetAnalInferenceEntity.targetYyyy), + mapSheetAnalInferenceEntity.stage, + mapSheetAnalInferenceEntity.gukyuinApplyDttm, + assignedCnt, + completeCnt, + skipCnt, + skipCnt, + // status, + percent, + mapSheetAnalInferenceEntity.createdDttm, + new CaseBuilder() + .when(mapSheetAnalInferenceEntity.inspectionClosedYn.eq("Y")) + .then(mapSheetAnalInferenceEntity.updatedDttm) + .otherwise((ZonedDateTime) null))) + .from(labelingAssignmentEntity) + .innerJoin(mapSheetAnalInferenceEntity) + .on(labelingAssignmentEntity.analUid.eq(mapSheetAnalInferenceEntity.id)) + .where( + labelingAssignmentEntity.analUid.in( + JPAExpressions.select(labelingAssignmentEntity.analUid) + .from(labelingAssignmentEntity) + .where(labelingAssignmentEntity.workerUid.eq(userId)) + .groupBy(labelingAssignmentEntity.analUid))) + .orderBy(percent.desc()) + .offset(pageable.getOffset()) + .limit(pageable.getPageSize()) + .fetch(); + + Long countQuery = + queryFactory + .select(mapSheetAnalInferenceEntity.id.count()) + .from(labelingAssignmentEntity) + .innerJoin(mapSheetAnalInferenceEntity) + .on(labelingAssignmentEntity.analUid.eq(mapSheetAnalInferenceEntity.id)) + .where( + labelingAssignmentEntity.analUid.in( + JPAExpressions.select(labelingAssignmentEntity.analUid) + .from(labelingAssignmentEntity) + .where(labelingAssignmentEntity.workerUid.eq(userId)) + .groupBy(labelingAssignmentEntity.analUid))) + .fetchOne(); + + return new PageImpl<>(list, pageable, countQuery); + } + + @Override + public Page workReviewerHistoryList(searchReq searchReq, String userId) { + + return null; + } }