From 2db7177eddced5637a3801096cc1e2626c135d89 Mon Sep 17 00:00:00 2001 From: Moon Date: Mon, 5 Jan 2026 14:22:38 +0900 Subject: [PATCH 1/6] =?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=A6=AC=EC=8A=A4=ED=8A=B8=20API=EB=B6=84?= =?UTF-8?q?=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../label/LabelWorkerApiController.java | 33 +++++ .../cd/kamcoback/label/dto/LabelWorkDto.java | 84 ++++++++++++ .../label/service/LabelAllocateService.java | 15 +-- .../label/service/LabelWorkService.java | 8 ++ .../postgres/core/LabelWorkCoreService.java | 7 + .../label/LabelWorkRepositoryCustom.java | 5 + .../label/LabelWorkRepositoryImpl.java | 125 ++++++++++++++++++ 7 files changed, 265 insertions(+), 12 deletions(-) diff --git a/src/main/java/com/kamco/cd/kamcoback/label/LabelWorkerApiController.java b/src/main/java/com/kamco/cd/kamcoback/label/LabelWorkerApiController.java index d07083e1..0337123c 100644 --- a/src/main/java/com/kamco/cd/kamcoback/label/LabelWorkerApiController.java +++ b/src/main/java/com/kamco/cd/kamcoback/label/LabelWorkerApiController.java @@ -5,6 +5,9 @@ import com.kamco.cd.kamcoback.config.api.ApiResponseDto; import com.kamco.cd.kamcoback.label.dto.LabelWorkDto; import com.kamco.cd.kamcoback.label.dto.LabelWorkDto.LabelWorkMng; import com.kamco.cd.kamcoback.label.dto.LabelWorkDto.LabelWorkMngSearchReq; +import com.kamco.cd.kamcoback.label.dto.LabelWorkDto.WorkerState; +import com.kamco.cd.kamcoback.label.dto.LabelWorkDto.WorkerStateSearchReq; +import com.kamco.cd.kamcoback.label.dto.WorkerStatsDto.WorkerStatistics; import com.kamco.cd.kamcoback.label.service.LabelWorkService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; @@ -61,4 +64,34 @@ public class LabelWorkerApiController { searchReq.setSize(size); return ApiResponseDto.ok(labelWorkService.labelWorkMngList(searchReq)); } + + @Operation(summary = "작업현황 관리 > 현황 목록 조회", description = "작업현황 관리 > 현황 목록 조회") + @ApiResponses( + value = { + @ApiResponse( + responseCode = "200", + description = "조회 성공", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = CommonCodeDto.Basic.class))), + @ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content), + @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) + }) + @GetMapping("/work-state-list") + public ApiResponseDto> findWorkStateList( + @Parameter(description = "유형", example = "LABELER") @RequestParam(required = false) String userRole, + @Parameter(description = "검색어", example = "20261201") @RequestParam(required = false) String searchVal, + @Parameter(description = "페이지 번호 (0부터 시작)", example = "0") @RequestParam(defaultValue = "0") + int page, + @Parameter(description = "페이지 크기", example = "20") @RequestParam(defaultValue = "20") + int size) { + + LabelWorkDto.WorkerStateSearchReq searchReq = new WorkerStateSearchReq(); + searchReq.setUserRole(userRole); + searchReq.setSearchVal(searchVal); + searchReq.setPage(page); + searchReq.setSize(size); + return ApiResponseDto.ok(labelWorkService.findlabelWorkStateList(searchReq)); + } } diff --git a/src/main/java/com/kamco/cd/kamcoback/label/dto/LabelWorkDto.java b/src/main/java/com/kamco/cd/kamcoback/label/dto/LabelWorkDto.java index 024f89b5..db5f5cb5 100644 --- a/src/main/java/com/kamco/cd/kamcoback/label/dto/LabelWorkDto.java +++ b/src/main/java/com/kamco/cd/kamcoback/label/dto/LabelWorkDto.java @@ -3,9 +3,11 @@ package com.kamco.cd.kamcoback.label.dto; import com.kamco.cd.kamcoback.common.utils.enums.Enums; import com.kamco.cd.kamcoback.common.utils.interfaces.JsonFormatDttm; import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.LabelMngState; +import com.kamco.cd.kamcoback.label.dto.WorkerStatsDto.DailyHistory; import io.swagger.v3.oas.annotations.media.Schema; import java.time.ZonedDateTime; import lombok.AllArgsConstructor; +import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; @@ -93,4 +95,86 @@ public class LabelWorkDto { return PageRequest.of(page, size); } } + + + @Getter + @Setter + @Builder + @NoArgsConstructor + @AllArgsConstructor + @Schema(description = "작업자 통계 응답") + public static class WorkerState { + + @Schema(description = "작업자 유형 (LABELER/INSPECTOR)") + private String userRole; + + @Schema(description = "작업자 ID (사번)") + private String name; + + @Schema(description = "작업자 이름") + private String userId; + + @Schema(description = "배정개수") + private Long assignedCnt; + + @Schema(description = "완료개수") + private Long doneCnt; + + @Schema(description = "Skip개수") + private Long skipCnt; + + @Schema(description = "Skip개수") + private Long day3AgoDoneCnt; + + @Schema(description = "Skip개수") + private Long day2AgoDoneCnt; + + @Schema(description = "Skip개수") + private Long day1AgoDoneCnt; + + public Long getremindCnt() { + return this.assignedCnt - this.doneCnt; + } + + public double getDoneRate() { + if (this.doneCnt == null || this.assignedCnt == 0) { + return 0.0; + } + return (double) this.doneCnt / this.assignedCnt * 100.0; + } + + public String getUserRoleName() { + if (this.userRole.equals("LABELER")) { + return "라벨러"; + } + return "검수자"; + } + + } + + @Schema(name = "WorkerStateSearchReq", description = "라벨작업관리 검색 요청") + @Getter + @Setter + @NoArgsConstructor + @AllArgsConstructor + public static class WorkerStateSearchReq { + + // 페이징 파라미터 + @Schema(description = "페이지 번호 (0부터 시작) ", example = "0") + private int page = 0; + + @Schema(description = "페이지 크기", example = "20") + private int size = 20; + + @Schema(description = "유형", example = "LABELER") + private String userRole; + + @Schema(description = "종료일", example = "20261201") + private String searchVal; + + public Pageable toPageable() { + + return PageRequest.of(page, size); + } + } } 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 ae0ada1d..6681d1e4 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 @@ -135,6 +135,8 @@ public class LabelAllocateService { // 작업 진행 현황 조회 var progressInfo = labelAllocateCoreService.findWorkProgressInfo(analUid); + + // 작업자 통계 조회 List workers = labelAllocateCoreService.findWorkerStatistics( @@ -155,20 +157,9 @@ public class LabelAllocateService { long average = (day1Count + day2Count + day3Count) / 3; - DailyHistory history = - DailyHistory.builder() - .day1Ago(day1Count) - .day2Ago(day2Count) - .day3Ago(day3Count) - .average(average) - .build(); - worker.setHistory(history); - // 정체 여부 판단 (3일 평균이 STAGNATION_THRESHOLD 미만일 때) - if (average < STAGNATION_THRESHOLD) { - worker.setIsStagnated(true); - } + } // 페이징 처리 diff --git a/src/main/java/com/kamco/cd/kamcoback/label/service/LabelWorkService.java b/src/main/java/com/kamco/cd/kamcoback/label/service/LabelWorkService.java index 3a8d6553..ceff3603 100644 --- a/src/main/java/com/kamco/cd/kamcoback/label/service/LabelWorkService.java +++ b/src/main/java/com/kamco/cd/kamcoback/label/service/LabelWorkService.java @@ -2,6 +2,8 @@ package com.kamco.cd.kamcoback.label.service; import com.kamco.cd.kamcoback.label.dto.LabelWorkDto; import com.kamco.cd.kamcoback.label.dto.LabelWorkDto.LabelWorkMng; +import com.kamco.cd.kamcoback.label.dto.LabelWorkDto.WorkerState; +import com.kamco.cd.kamcoback.label.dto.WorkerStatsDto.WorkerStatistics; import com.kamco.cd.kamcoback.postgres.core.LabelWorkCoreService; import lombok.extern.slf4j.Slf4j; import org.springframework.data.domain.Page; @@ -21,4 +23,10 @@ public class LabelWorkService { return labelWorkCoreService.labelWorkMngList(searchReq); } + + + public Page findlabelWorkStateList(LabelWorkDto.WorkerStateSearchReq searchReq) { + + return labelWorkCoreService.findlabelWorkStateList(searchReq); + } } diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/core/LabelWorkCoreService.java b/src/main/java/com/kamco/cd/kamcoback/postgres/core/LabelWorkCoreService.java index a1be92a5..3336c07d 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/core/LabelWorkCoreService.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/core/LabelWorkCoreService.java @@ -2,6 +2,8 @@ package com.kamco.cd.kamcoback.postgres.core; import com.kamco.cd.kamcoback.label.dto.LabelWorkDto; import com.kamco.cd.kamcoback.label.dto.LabelWorkDto.LabelWorkMng; +import com.kamco.cd.kamcoback.label.dto.LabelWorkDto.WorkerState; +import com.kamco.cd.kamcoback.label.dto.WorkerStatsDto.WorkerStatistics; import com.kamco.cd.kamcoback.postgres.repository.label.LabelWorkRepository; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; @@ -16,4 +18,9 @@ public class LabelWorkCoreService { public Page labelWorkMngList(LabelWorkDto.LabelWorkMngSearchReq searchReq) { return labelWorkRepository.labelWorkMngList(searchReq); } + + public Page findlabelWorkStateList(LabelWorkDto.WorkerStateSearchReq searchReq) + { + return labelWorkRepository.findlabelWorkStateList(searchReq); + }; } diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/label/LabelWorkRepositoryCustom.java b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/label/LabelWorkRepositoryCustom.java index 6a27f5d0..c123cf9f 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/label/LabelWorkRepositoryCustom.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/label/LabelWorkRepositoryCustom.java @@ -2,9 +2,14 @@ package com.kamco.cd.kamcoback.postgres.repository.label; import com.kamco.cd.kamcoback.label.dto.LabelWorkDto; import com.kamco.cd.kamcoback.label.dto.LabelWorkDto.LabelWorkMng; +import com.kamco.cd.kamcoback.label.dto.LabelWorkDto.WorkerState; +import com.kamco.cd.kamcoback.label.dto.WorkerStatsDto.WorkerStatistics; import org.springframework.data.domain.Page; public interface LabelWorkRepositoryCustom { public Page labelWorkMngList(LabelWorkDto.LabelWorkMngSearchReq searchReq); + + Page findlabelWorkStateList(LabelWorkDto.WorkerStateSearchReq searchReq); + } diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/label/LabelWorkRepositoryImpl.java b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/label/LabelWorkRepositoryImpl.java index e17da42c..8d3e3154 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/label/LabelWorkRepositoryImpl.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/label/LabelWorkRepositoryImpl.java @@ -1,10 +1,18 @@ package com.kamco.cd.kamcoback.postgres.repository.label; +import static com.kamco.cd.kamcoback.postgres.entity.QLabelingAssignmentEntity.labelingAssignmentEntity; +import static com.kamco.cd.kamcoback.postgres.entity.QMapInkx5kEntity.mapInkx5kEntity; import static com.kamco.cd.kamcoback.postgres.entity.QMapSheetAnalDataInferenceEntity.mapSheetAnalDataInferenceEntity; import static com.kamco.cd.kamcoback.postgres.entity.QMapSheetAnalDataInferenceGeomEntity.mapSheetAnalDataInferenceGeomEntity; +import static com.kamco.cd.kamcoback.postgres.entity.QMapSheetMngEntity.mapSheetMngEntity; +import static com.kamco.cd.kamcoback.postgres.entity.QMapSheetMngHstEntity.mapSheetMngHstEntity; +import static com.kamco.cd.kamcoback.postgres.entity.QMemberEntity.memberEntity; import com.kamco.cd.kamcoback.label.dto.LabelWorkDto; import com.kamco.cd.kamcoback.label.dto.LabelWorkDto.LabelWorkMng; +import com.kamco.cd.kamcoback.label.dto.LabelWorkDto.WorkerState; +import com.kamco.cd.kamcoback.label.dto.WorkerStatsDto.WorkerStatistics; +import com.kamco.cd.kamcoback.mapsheet.dto.MapSheetMngDto; import com.kamco.cd.kamcoback.postgres.entity.MapSheetAnalDataGeomEntity; import com.querydsl.core.BooleanBuilder; import com.querydsl.core.types.Projections; @@ -14,6 +22,7 @@ import com.querydsl.core.types.dsl.StringExpression; import com.querydsl.jpa.impl.JPAQueryFactory; import jakarta.persistence.EntityManager; import jakarta.persistence.PersistenceContext; +import java.time.LocalDate; import java.time.format.DateTimeFormatter; import java.util.List; import lombok.extern.slf4j.Slf4j; @@ -135,4 +144,120 @@ public class LabelWorkRepositoryImpl extends QuerydslRepositorySupport return new PageImpl<>(foundContent, pageable, countQuery); } + + + @Override + public Page findlabelWorkStateList(LabelWorkDto.WorkerStateSearchReq searchReq){ + Pageable pageable = PageRequest.of(searchReq.getPage(), searchReq.getSize()); + BooleanBuilder whereBuilder = new BooleanBuilder(); + BooleanBuilder whereSubBuilder = new BooleanBuilder(); + + LocalDate threeDaysAgo = LocalDate.now().minusDays(3); + String s3 = threeDaysAgo.format(DateTimeFormatter.ofPattern("YYYY-MM-DD")); + + LocalDate twoDaysAgo = LocalDate.now().minusDays(2); + String s2 = twoDaysAgo.format(DateTimeFormatter.ofPattern("YYYY-MM-DD")); + + LocalDate oneDaysAgo = LocalDate.now().minusDays(1); + String s1 = oneDaysAgo.format(DateTimeFormatter.ofPattern("YYYY-MM-DD")); + + if (searchReq.getUserRole() != null && ! searchReq.getUserRole().isEmpty()) { + whereSubBuilder.and(memberEntity.userRole.eq(searchReq.getUserRole())); + } + + if (searchReq.getSearchVal() != null && ! searchReq.getSearchVal().isEmpty()) { + whereSubBuilder.and( + Expressions.stringTemplate( + "{0}",memberEntity.userId) + .likeIgnoreCase("%" + searchReq.getSearchVal() + "%") + .or( + Expressions.stringTemplate( + "{0}",memberEntity.name) + .likeIgnoreCase("%" + searchReq.getSearchVal() + "%") + ) + ); + } + + whereSubBuilder.and( + labelingAssignmentEntity.workerUid.eq(memberEntity.userId)); + + List foundContent = + queryFactory + .select( + Projections.constructor( + WorkerState.class, + memberEntity.userRole, + memberEntity.name, + memberEntity.userId, + labelingAssignmentEntity.workerUid.count().as("assignedCnt"), + new CaseBuilder() + .when(labelingAssignmentEntity.workState.eq("DONE")) + .then(1L) + .otherwise(0L) + .sum() + .as("doneCnt"), + new CaseBuilder() + .when(labelingAssignmentEntity.workState.eq("SKIP")) + .then(1L) + .otherwise(0L) + .sum() + .as("skipCnt"), + new CaseBuilder() + .when(labelingAssignmentEntity.workState.eq("DONE") + .and( + Expressions.stringTemplate( + "to_char({0}, 'YYYY-MM-DD')", labelingAssignmentEntity.modifiedDate).eq(s3) ) + ) + .then(1L) + .otherwise(0L) + .sum() + .as("day3AgoDoneCnt"), + new CaseBuilder() + .when(labelingAssignmentEntity.workState.eq("DONE") + .and( + Expressions.stringTemplate( + "to_char({0}, 'YYYY-MM-DD')", labelingAssignmentEntity.modifiedDate).eq(s2) ) + ) + .then(1L) + .otherwise(0L) + .sum() + .as("day2AgoDoneCnt"), + new CaseBuilder() + .when(labelingAssignmentEntity.workState.eq("DONE") + .and( + Expressions.stringTemplate( + "to_char({0}, 'YYYY-MM-DD')", labelingAssignmentEntity.modifiedDate).eq(s1) ) + ) + .then(1L) + .otherwise(0L) + .sum() + .as("day1AgoDoneCnt") + )) + .from(labelingAssignmentEntity) + .innerJoin(memberEntity) + .on(whereSubBuilder) + .where(whereBuilder) + .groupBy( + memberEntity.userRole, + memberEntity.name, + memberEntity.userId) + .offset(pageable.getOffset()) + .limit(pageable.getPageSize()) + .fetch(); + + /* + Long countQuery = + queryFactory + .select(labelingAssignmentEntity.workerUid.count()) + .from(labelingAssignmentEntity) + .where(whereBuilder) + .fetchOne(); + */ + + Long countQuery = foundContent.stream().count(); + + return new PageImpl<>(foundContent, pageable, countQuery); + } + + } From 539831c71268eedf185f8076c7b26b1e232f9f12 Mon Sep 17 00:00:00 2001 From: teddy Date: Mon, 5 Jan 2026 14:39:08 +0900 Subject: [PATCH 2/6] =?UTF-8?q?=EB=9D=BC=EB=B2=A8=EB=A7=81=EC=9E=91?= =?UTF-8?q?=EC=97=85=20=EA=B4=80=EB=A6=AC=20=EB=AA=A9=EB=A1=9D=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Innopam/InnopamApiController.java | 28 ++++++++++++++- .../postgres/core/DetectMastCoreService.java | 5 +++ .../DetectMastRepositoryCustom.java | 3 ++ .../repository/DetectMastRepositoryImpl.java | 35 +++++++++++++++++++ .../Innopam/service/DetectMastService.java | 24 ++++++++++++- .../InferenceResultRepositoryImpl.java | 4 +-- .../label/LabelWorkRepositoryImpl.java | 10 +++++- 7 files changed, 103 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/kamco/cd/kamcoback/Innopam/InnopamApiController.java b/src/main/java/com/kamco/cd/kamcoback/Innopam/InnopamApiController.java index 56f027e4..e547f1b8 100644 --- a/src/main/java/com/kamco/cd/kamcoback/Innopam/InnopamApiController.java +++ b/src/main/java/com/kamco/cd/kamcoback/Innopam/InnopamApiController.java @@ -18,6 +18,7 @@ import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; @@ -113,7 +114,7 @@ public class InnopamApiController { return detectMastService.selectDetectMast(dtctMstId); } - @Operation(summary = "탐지객체 PNU 리스트 조회", description = "탐지객체 PNU 리스트 조회") + @Operation(summary = "탐지객체 랜덤 PNU 리스트 조회", description = "탐지객체 PNU 랜덤값을 생성해서 보여준다") @ApiResponses( value = { @ApiResponse( @@ -149,4 +150,29 @@ public class InnopamApiController { detectMastSearch.setFeatureId(featureId); return new FeaturePnuDto(); } + + @Operation( + summary = "탐지객체 랜덤 PNU GEOM 업데이트(이노펨에 없는 API)", + description = "탐지객체 랜덤 PNU GEOM 업데이트(이노펨에 없는 API)") + @ApiResponses( + value = { + @ApiResponse( + responseCode = "201", + description = "pnu 업데이트 성공", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = Integer.class))), + @ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content), + @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) + }) + @PutMapping("/pnu/{cprsBfYr}/{cprsAfYr}/{dtctSno}") + public Integer updatePnuList( + @PathVariable String cprsBfYr, @PathVariable String cprsAfYr, @PathVariable String dtctSno) { + DetectMastSearch detectMastSearch = new DetectMastSearch(); + detectMastSearch.setCprsAdYr(cprsAfYr); + detectMastSearch.setCprsBfYr(cprsBfYr); + detectMastSearch.setDtctSno(Integer.parseInt(dtctSno)); + return detectMastService.updatePnuData(detectMastSearch); + } } diff --git a/src/main/java/com/kamco/cd/kamcoback/Innopam/postgres/core/DetectMastCoreService.java b/src/main/java/com/kamco/cd/kamcoback/Innopam/postgres/core/DetectMastCoreService.java index 6125209b..6a77bcee 100644 --- a/src/main/java/com/kamco/cd/kamcoback/Innopam/postgres/core/DetectMastCoreService.java +++ b/src/main/java/com/kamco/cd/kamcoback/Innopam/postgres/core/DetectMastCoreService.java @@ -4,6 +4,7 @@ import com.kamco.cd.kamcoback.Innopam.dto.DetectMastDto; import com.kamco.cd.kamcoback.Innopam.dto.DetectMastDto.Basic; import com.kamco.cd.kamcoback.Innopam.dto.DetectMastDto.DetectMastReq; import com.kamco.cd.kamcoback.Innopam.dto.DetectMastDto.DetectMastSearch; +import com.kamco.cd.kamcoback.Innopam.dto.DetectMastDto.FeaturePnuDto; import com.kamco.cd.kamcoback.Innopam.postgres.entity.DetectMastEntity; import com.kamco.cd.kamcoback.Innopam.postgres.repository.DetectMastRepository; import java.util.List; @@ -59,4 +60,8 @@ public class DetectMastCoreService { DetectMastEntity detectMastEntity = detectMastRepository.findPnuData(detectMast); return detectMastEntity.getPathNm(); } + + public Integer updatePnu(List list) { + return detectMastRepository.updateGeomPnu(list); + } } diff --git a/src/main/java/com/kamco/cd/kamcoback/Innopam/postgres/repository/DetectMastRepositoryCustom.java b/src/main/java/com/kamco/cd/kamcoback/Innopam/postgres/repository/DetectMastRepositoryCustom.java index 93ce4fb4..47d1ea99 100644 --- a/src/main/java/com/kamco/cd/kamcoback/Innopam/postgres/repository/DetectMastRepositoryCustom.java +++ b/src/main/java/com/kamco/cd/kamcoback/Innopam/postgres/repository/DetectMastRepositoryCustom.java @@ -1,6 +1,7 @@ package com.kamco.cd.kamcoback.Innopam.postgres.repository; import com.kamco.cd.kamcoback.Innopam.dto.DetectMastDto.DetectMastSearch; +import com.kamco.cd.kamcoback.Innopam.dto.DetectMastDto.FeaturePnuDto; import com.kamco.cd.kamcoback.Innopam.postgres.entity.DetectMastEntity; import java.util.List; @@ -9,4 +10,6 @@ public interface DetectMastRepositoryCustom { public List findDetectMastList(DetectMastSearch detectMast); public DetectMastEntity findPnuData(DetectMastSearch detectMast); + + Integer updateGeomPnu(List list); } diff --git a/src/main/java/com/kamco/cd/kamcoback/Innopam/postgres/repository/DetectMastRepositoryImpl.java b/src/main/java/com/kamco/cd/kamcoback/Innopam/postgres/repository/DetectMastRepositoryImpl.java index c2c658e2..78888af4 100644 --- a/src/main/java/com/kamco/cd/kamcoback/Innopam/postgres/repository/DetectMastRepositoryImpl.java +++ b/src/main/java/com/kamco/cd/kamcoback/Innopam/postgres/repository/DetectMastRepositoryImpl.java @@ -2,10 +2,14 @@ package com.kamco.cd.kamcoback.Innopam.postgres.repository; import static com.kamco.cd.kamcoback.Innopam.postgres.entity.QDetectMastEntity.detectMastEntity; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; import com.kamco.cd.kamcoback.Innopam.dto.DetectMastDto.DetectMastSearch; +import com.kamco.cd.kamcoback.Innopam.dto.DetectMastDto.FeaturePnuDto; import com.kamco.cd.kamcoback.Innopam.postgres.entity.DetectMastEntity; import com.querydsl.core.BooleanBuilder; import com.querydsl.jpa.impl.JPAQueryFactory; +import jakarta.persistence.EntityManager; import java.util.List; import lombok.RequiredArgsConstructor; import org.apache.commons.lang3.StringUtils; @@ -15,7 +19,9 @@ import org.springframework.stereotype.Repository; @RequiredArgsConstructor public class DetectMastRepositoryImpl implements DetectMastRepositoryCustom { + private final EntityManager em; private final JPAQueryFactory queryFactory; + private final ObjectMapper objectMapper; @Override public List findDetectMastList(DetectMastSearch detectMast) { @@ -56,4 +62,33 @@ public class DetectMastRepositoryImpl implements DetectMastRepositoryCustom { .where(whereBuilder) .fetchOne(); } + + @Override + public Integer updateGeomPnu(List list) { + if (list == null || list.isEmpty()) { + return 0; + } + + String sql = + """ + UPDATE tb_map_sheet_anal_data_inference_geom g + SET pnu = j.pnu + FROM ( + SELECT + (elem->>'featureId')::uuid AS feature_uuid, + (elem->>'pnu')::bigint AS pnu + FROM jsonb_array_elements(CAST(:json AS jsonb)) AS elem + ) j + WHERE g.uuid = j.feature_uuid; + """; + + String json = ""; + try { + json = objectMapper.writeValueAsString(list); + } catch (JsonProcessingException e) { + throw new RuntimeException("PNU 업데이트 실패", e); + } + + return em.createNativeQuery(sql).setParameter("json", json).executeUpdate(); + } } diff --git a/src/main/java/com/kamco/cd/kamcoback/Innopam/service/DetectMastService.java b/src/main/java/com/kamco/cd/kamcoback/Innopam/service/DetectMastService.java index 21ea3d64..a2f41dfe 100644 --- a/src/main/java/com/kamco/cd/kamcoback/Innopam/service/DetectMastService.java +++ b/src/main/java/com/kamco/cd/kamcoback/Innopam/service/DetectMastService.java @@ -57,12 +57,34 @@ public class DetectMastService { String dirPath = "local".equals(profile) - ? "/Users/bokmin/detect/result/2023_2024/4" + ? "/Users/bokmin/detect/result/" + + detectMast.getCprsBfYr() + + "_" + + detectMast.getCprsAdYr() + + "/" + + detectMast.getDtctSno() : detectMastCoreService.findPnuData(detectMast); return extractFeaturePnusRandom(dirPath); } + @Transactional + public Integer updatePnuData(DetectMastSearch detectMast) { + + String dirPath = + "local".equals(profile) + ? "/Users/bokmin/detect/result/" + + detectMast.getCprsBfYr() + + "_" + + detectMast.getCprsAdYr() + + "/" + + detectMast.getDtctSno() + : detectMastCoreService.findPnuData(detectMast); + + List list = extractFeaturePnusRandom(dirPath); + return detectMastCoreService.updatePnu(list); + } + /** 하위 폴더까지 .geojson 파일들에서 polygon_id만 뽑음 병렬처리(parallel) 제거: IO + parallel은 거의 항상 느려짐 */ private List extractFeaturePnusRandom(String dirPath) { diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/Inference/InferenceResultRepositoryImpl.java b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/Inference/InferenceResultRepositoryImpl.java index 37f0c8a6..2ea1a66a 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/Inference/InferenceResultRepositoryImpl.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/Inference/InferenceResultRepositoryImpl.java @@ -5,7 +5,6 @@ import com.kamco.cd.kamcoback.postgres.entity.QMapSheetAnalDataInferenceEntity; import com.kamco.cd.kamcoback.postgres.entity.QMapSheetAnalDataInferenceGeomEntity; import com.querydsl.jpa.impl.JPAQueryFactory; import jakarta.persistence.EntityManager; -import jakarta.persistence.PersistenceContext; import java.time.ZonedDateTime; import java.util.List; import lombok.RequiredArgsConstructor; @@ -16,8 +15,7 @@ import org.springframework.stereotype.Repository; public class InferenceResultRepositoryImpl implements InferenceResultRepositoryCustom { private final JPAQueryFactory queryFactory; - - @PersistenceContext private final EntityManager em; + private final EntityManager em; /** tb_map_sheet_anal_data_inference */ private final QMapSheetAnalDataInferenceEntity inferenceEntity = diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/label/LabelWorkRepositoryImpl.java b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/label/LabelWorkRepositoryImpl.java index 761d9f12..55d5586f 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/label/LabelWorkRepositoryImpl.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/label/LabelWorkRepositoryImpl.java @@ -124,7 +124,15 @@ public class LabelWorkRepositoryImpl extends QuerydslRepositorySupport mapSheetAnalInferenceEntity.stage, mapSheetAnalDataInferenceEntity.createdDttm.min(), mapSheetAnalDataInferenceGeomEntity.dataUid.count(), - mapSheetAnalDataInferenceGeomEntity.dataUid.count(), + new CaseBuilder() + .when( + mapSheetAnalDataInferenceGeomEntity + .pnu + .isNotNull() + .and(mapSheetAnalDataInferenceGeomEntity.pnu.ne(0L))) + .then(1L) + .otherwise(0L) + .sum(), new CaseBuilder() .when(mapSheetAnalDataInferenceGeomEntity.labelState.eq("STOP")) .then(1L) From 338e9c448c9548876cd0ff4338d85105adff30ca Mon Sep 17 00:00:00 2001 From: teddy Date: Mon, 5 Jan 2026 14:46:26 +0900 Subject: [PATCH 3/6] =?UTF-8?q?=EB=9D=BC=EB=B2=A8=EB=A7=81=EC=9E=91?= =?UTF-8?q?=EC=97=85=20=EA=B4=80=EB=A6=AC=20=EB=AA=A9=EB=A1=9D=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../label/LabelWorkerApiController.java | 37 ++-- .../cd/kamcoback/label/dto/LabelWorkDto.java | 5 +- .../label/service/LabelAllocateService.java | 17 +- .../label/service/LabelWorkService.java | 4 +- .../postgres/core/LabelWorkCoreService.java | 11 +- .../label/LabelWorkRepositoryCustom.java | 4 +- .../label/LabelWorkRepositoryImpl.java | 180 +++++++++--------- 7 files changed, 118 insertions(+), 140 deletions(-) diff --git a/src/main/java/com/kamco/cd/kamcoback/label/LabelWorkerApiController.java b/src/main/java/com/kamco/cd/kamcoback/label/LabelWorkerApiController.java index fa7cf915..3d85d264 100644 --- a/src/main/java/com/kamco/cd/kamcoback/label/LabelWorkerApiController.java +++ b/src/main/java/com/kamco/cd/kamcoback/label/LabelWorkerApiController.java @@ -8,7 +8,6 @@ import com.kamco.cd.kamcoback.label.dto.LabelWorkDto.LabelWorkMngDetail; import com.kamco.cd.kamcoback.label.dto.LabelWorkDto.LabelWorkMngSearchReq; import com.kamco.cd.kamcoback.label.dto.LabelWorkDto.WorkerState; import com.kamco.cd.kamcoback.label.dto.LabelWorkDto.WorkerStateSearchReq; -import com.kamco.cd.kamcoback.label.dto.WorkerStatsDto.WorkerStatistics; import com.kamco.cd.kamcoback.label.service.LabelWorkService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; @@ -108,25 +107,27 @@ public class LabelWorkerApiController { @Operation(summary = "작업현황 관리 > 현황 목록 조회", description = "작업현황 관리 > 현황 목록 조회") @ApiResponses( - value = { - @ApiResponse( - responseCode = "200", - description = "조회 성공", - content = - @Content( - mediaType = "application/json", - schema = @Schema(implementation = CommonCodeDto.Basic.class))), - @ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content), - @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) - }) + value = { + @ApiResponse( + responseCode = "200", + description = "조회 성공", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = Page.class))), + @ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content), + @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) + }) @GetMapping("/work-state-list") public ApiResponseDto> findWorkStateList( - @Parameter(description = "유형", example = "LABELER") @RequestParam(required = false) String userRole, - @Parameter(description = "검색어", example = "20261201") @RequestParam(required = false) String searchVal, - @Parameter(description = "페이지 번호 (0부터 시작)", example = "0") @RequestParam(defaultValue = "0") - int page, - @Parameter(description = "페이지 크기", example = "20") @RequestParam(defaultValue = "20") - int size) { + @Parameter(description = "유형", example = "LABELER") @RequestParam(required = false) + String userRole, + @Parameter(description = "검색어", example = "20261201") @RequestParam(required = false) + String searchVal, + @Parameter(description = "페이지 번호 (0부터 시작)", example = "0") @RequestParam(defaultValue = "0") + int page, + @Parameter(description = "페이지 크기", example = "20") @RequestParam(defaultValue = "20") + int size) { LabelWorkDto.WorkerStateSearchReq searchReq = new WorkerStateSearchReq(); searchReq.setUserRole(userRole); diff --git a/src/main/java/com/kamco/cd/kamcoback/label/dto/LabelWorkDto.java b/src/main/java/com/kamco/cd/kamcoback/label/dto/LabelWorkDto.java index d895ad1b..de845206 100644 --- a/src/main/java/com/kamco/cd/kamcoback/label/dto/LabelWorkDto.java +++ b/src/main/java/com/kamco/cd/kamcoback/label/dto/LabelWorkDto.java @@ -4,7 +4,6 @@ import com.fasterxml.jackson.annotation.JsonProperty; import com.kamco.cd.kamcoback.common.utils.enums.Enums; import com.kamco.cd.kamcoback.common.utils.interfaces.JsonFormatDttm; import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.LabelMngState; -import com.kamco.cd.kamcoback.label.dto.WorkerStatsDto.DailyHistory; import io.swagger.v3.oas.annotations.media.Schema; import java.time.ZonedDateTime; import java.util.UUID; @@ -130,7 +129,6 @@ public class LabelWorkDto { } } - @Getter @Setter @Builder @@ -167,7 +165,7 @@ public class LabelWorkDto { private Long day1AgoDoneCnt; public Long getremindCnt() { - return this.assignedCnt - this.doneCnt; + return this.assignedCnt - this.doneCnt; } public double getDoneRate() { @@ -183,7 +181,6 @@ public class LabelWorkDto { } return "검수자"; } - } @Schema(name = "WorkerStateSearchReq", description = "라벨작업관리 검색 요청") 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 6681d1e4..df8b039a 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 @@ -8,7 +8,6 @@ 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.TargetUser; import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.UserList; -import com.kamco.cd.kamcoback.label.dto.WorkerStatsDto.DailyHistory; import com.kamco.cd.kamcoback.label.dto.WorkerStatsDto.WorkerListResponse; import com.kamco.cd.kamcoback.label.dto.WorkerStatsDto.WorkerStatistics; import com.kamco.cd.kamcoback.postgres.core.LabelAllocateCoreService; @@ -122,12 +121,7 @@ public class LabelAllocateService { * @return 작업자 목록 및 통계 */ public WorkerListResponse getWorkerStatistics( - Long analUid, - String workerType, - String search, - String sortType, - Integer page, - Integer size) { + Long analUid, String workerType, String search, String sortType, Integer page, Integer size) { // 프로젝트 정보 조회 (analUid가 있을 때만) var projectInfo = labelAllocateCoreService.findProjectInfo(analUid); @@ -135,12 +129,9 @@ public class LabelAllocateService { // 작업 진행 현황 조회 var progressInfo = labelAllocateCoreService.findWorkProgressInfo(analUid); - - // 작업자 통계 조회 List workers = - labelAllocateCoreService.findWorkerStatistics( - analUid, workerType, search, sortType); + labelAllocateCoreService.findWorkerStatistics(analUid, workerType, search, sortType); // 각 작업자별 3일치 처리량 조회 LocalDate today = LocalDate.now(); @@ -156,10 +147,6 @@ public class LabelAllocateService { worker.getWorkerId(), workerType, today.minusDays(3), analUid); long average = (day1Count + day2Count + day3Count) / 3; - - - - } // 페이징 처리 diff --git a/src/main/java/com/kamco/cd/kamcoback/label/service/LabelWorkService.java b/src/main/java/com/kamco/cd/kamcoback/label/service/LabelWorkService.java index 3e336a38..f6405984 100644 --- a/src/main/java/com/kamco/cd/kamcoback/label/service/LabelWorkService.java +++ b/src/main/java/com/kamco/cd/kamcoback/label/service/LabelWorkService.java @@ -3,9 +3,8 @@ package com.kamco.cd.kamcoback.label.service; import com.kamco.cd.kamcoback.label.dto.LabelWorkDto; import com.kamco.cd.kamcoback.label.dto.LabelWorkDto.ChangeDetectYear; import com.kamco.cd.kamcoback.label.dto.LabelWorkDto.LabelWorkMng; -import com.kamco.cd.kamcoback.label.dto.LabelWorkDto.WorkerState; -import com.kamco.cd.kamcoback.label.dto.WorkerStatsDto.WorkerStatistics; import com.kamco.cd.kamcoback.label.dto.LabelWorkDto.LabelWorkMngDetail; +import com.kamco.cd.kamcoback.label.dto.LabelWorkDto.WorkerState; import com.kamco.cd.kamcoback.postgres.core.LabelWorkCoreService; import java.util.List; import java.util.UUID; @@ -52,7 +51,6 @@ public class LabelWorkService { return labelWorkCoreService.getChangeDetectYear(); } - public Page findlabelWorkStateList(LabelWorkDto.WorkerStateSearchReq searchReq) { return labelWorkCoreService.findlabelWorkStateList(searchReq); diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/core/LabelWorkCoreService.java b/src/main/java/com/kamco/cd/kamcoback/postgres/core/LabelWorkCoreService.java index ffec3b34..4b236c13 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/core/LabelWorkCoreService.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/core/LabelWorkCoreService.java @@ -1,10 +1,13 @@ package com.kamco.cd.kamcoback.postgres.core; import com.kamco.cd.kamcoback.label.dto.LabelWorkDto; +import com.kamco.cd.kamcoback.label.dto.LabelWorkDto.ChangeDetectYear; import com.kamco.cd.kamcoback.label.dto.LabelWorkDto.LabelWorkMng; +import com.kamco.cd.kamcoback.label.dto.LabelWorkDto.LabelWorkMngDetail; import com.kamco.cd.kamcoback.label.dto.LabelWorkDto.WorkerState; -import com.kamco.cd.kamcoback.label.dto.WorkerStatsDto.WorkerStatistics; import com.kamco.cd.kamcoback.postgres.repository.label.LabelWorkRepository; +import java.util.List; +import java.util.UUID; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.stereotype.Service; @@ -40,10 +43,10 @@ public class LabelWorkCoreService { return labelWorkRepository.labelWorkMngList(searchReq); } - public Page findlabelWorkStateList(LabelWorkDto.WorkerStateSearchReq searchReq) - { + public Page findlabelWorkStateList(LabelWorkDto.WorkerStateSearchReq searchReq) { return labelWorkRepository.findlabelWorkStateList(searchReq); - }; + } + ; /** * 작업배정 정보 조회 diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/label/LabelWorkRepositoryCustom.java b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/label/LabelWorkRepositoryCustom.java index 4db287c3..baf773e7 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/label/LabelWorkRepositoryCustom.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/label/LabelWorkRepositoryCustom.java @@ -2,9 +2,8 @@ package com.kamco.cd.kamcoback.postgres.repository.label; import com.kamco.cd.kamcoback.label.dto.LabelWorkDto; import com.kamco.cd.kamcoback.label.dto.LabelWorkDto.LabelWorkMng; -import com.kamco.cd.kamcoback.label.dto.LabelWorkDto.WorkerState; -import com.kamco.cd.kamcoback.label.dto.WorkerStatsDto.WorkerStatistics; import com.kamco.cd.kamcoback.label.dto.LabelWorkDto.LabelWorkMngDetail; +import com.kamco.cd.kamcoback.label.dto.LabelWorkDto.WorkerState; import com.kamco.cd.kamcoback.postgres.entity.MapSheetAnalInferenceEntity; import java.util.List; import java.util.UUID; @@ -19,5 +18,4 @@ public interface LabelWorkRepositoryCustom { LabelWorkMngDetail findLabelWorkMngDetail(UUID uuid); Page findlabelWorkStateList(LabelWorkDto.WorkerStateSearchReq searchReq); - } diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/label/LabelWorkRepositoryImpl.java b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/label/LabelWorkRepositoryImpl.java index 0b56ace1..dbc1d4cb 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/label/LabelWorkRepositoryImpl.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/label/LabelWorkRepositoryImpl.java @@ -1,21 +1,15 @@ package com.kamco.cd.kamcoback.postgres.repository.label; import static com.kamco.cd.kamcoback.postgres.entity.QLabelingAssignmentEntity.labelingAssignmentEntity; -import static com.kamco.cd.kamcoback.postgres.entity.QLabelingAssignmentEntity.labelingAssignmentEntity; -import static com.kamco.cd.kamcoback.postgres.entity.QMapInkx5kEntity.mapInkx5kEntity; import static com.kamco.cd.kamcoback.postgres.entity.QMapSheetAnalDataInferenceEntity.mapSheetAnalDataInferenceEntity; import static com.kamco.cd.kamcoback.postgres.entity.QMapSheetAnalDataInferenceGeomEntity.mapSheetAnalDataInferenceGeomEntity; import static com.kamco.cd.kamcoback.postgres.entity.QMapSheetAnalInferenceEntity.mapSheetAnalInferenceEntity; -import static com.kamco.cd.kamcoback.postgres.entity.QMapSheetMngEntity.mapSheetMngEntity; -import static com.kamco.cd.kamcoback.postgres.entity.QMapSheetMngHstEntity.mapSheetMngHstEntity; import static com.kamco.cd.kamcoback.postgres.entity.QMemberEntity.memberEntity; import com.kamco.cd.kamcoback.label.dto.LabelWorkDto; import com.kamco.cd.kamcoback.label.dto.LabelWorkDto.LabelWorkMng; import com.kamco.cd.kamcoback.label.dto.LabelWorkDto.LabelWorkMngDetail; import com.kamco.cd.kamcoback.label.dto.LabelWorkDto.WorkerState; -import com.kamco.cd.kamcoback.label.dto.WorkerStatsDto.WorkerStatistics; -import com.kamco.cd.kamcoback.mapsheet.dto.MapSheetMngDto; import com.kamco.cd.kamcoback.postgres.entity.MapSheetAnalDataGeomEntity; import com.kamco.cd.kamcoback.postgres.entity.MapSheetAnalInferenceEntity; import com.querydsl.core.BooleanBuilder; @@ -196,22 +190,21 @@ public class LabelWorkRepositoryImpl extends QuerydslRepositorySupport */ Long total = - queryFactory - .select(mapSheetAnalInferenceEntity.uuid.countDistinct()) - .from(mapSheetAnalInferenceEntity) - .innerJoin(mapSheetAnalDataInferenceEntity) - .on(whereSubDataBuilder) - .innerJoin(mapSheetAnalDataInferenceGeomEntity) - .on(whereSubBuilder) - .where(whereBuilder) - .fetchOne(); + queryFactory + .select(mapSheetAnalInferenceEntity.uuid.countDistinct()) + .from(mapSheetAnalInferenceEntity) + .innerJoin(mapSheetAnalDataInferenceEntity) + .on(whereSubDataBuilder) + .innerJoin(mapSheetAnalDataInferenceGeomEntity) + .on(whereSubBuilder) + .where(whereBuilder) + .fetchOne(); return new PageImpl<>(foundContent, pageable, total); } - @Override - public Page findlabelWorkStateList(LabelWorkDto.WorkerStateSearchReq searchReq){ + public Page findlabelWorkStateList(LabelWorkDto.WorkerStateSearchReq searchReq) { Pageable pageable = PageRequest.of(searchReq.getPage(), searchReq.getSize()); BooleanBuilder whereBuilder = new BooleanBuilder(); BooleanBuilder whereSubBuilder = new BooleanBuilder(); @@ -225,89 +218,92 @@ public class LabelWorkRepositoryImpl extends QuerydslRepositorySupport LocalDate oneDaysAgo = LocalDate.now().minusDays(1); String s1 = oneDaysAgo.format(DateTimeFormatter.ofPattern("YYYY-MM-DD")); - if (searchReq.getUserRole() != null && ! searchReq.getUserRole().isEmpty()) { + if (searchReq.getUserRole() != null && !searchReq.getUserRole().isEmpty()) { whereSubBuilder.and(memberEntity.userRole.eq(searchReq.getUserRole())); } - if (searchReq.getSearchVal() != null && ! searchReq.getSearchVal().isEmpty()) { + if (searchReq.getSearchVal() != null && !searchReq.getSearchVal().isEmpty()) { whereSubBuilder.and( - Expressions.stringTemplate( - "{0}",memberEntity.userId) - .likeIgnoreCase("%" + searchReq.getSearchVal() + "%") - .or( - Expressions.stringTemplate( - "{0}",memberEntity.name) + Expressions.stringTemplate("{0}", memberEntity.userId) .likeIgnoreCase("%" + searchReq.getSearchVal() + "%") - ) - ); + .or( + Expressions.stringTemplate("{0}", memberEntity.name) + .likeIgnoreCase("%" + searchReq.getSearchVal() + "%"))); } - whereSubBuilder.and( - labelingAssignmentEntity.workerUid.eq(memberEntity.userId)); + whereSubBuilder.and(labelingAssignmentEntity.workerUid.eq(memberEntity.userId)); List foundContent = - queryFactory - .select( - Projections.constructor( - WorkerState.class, - memberEntity.userRole, - memberEntity.name, - memberEntity.userId, - labelingAssignmentEntity.workerUid.count().as("assignedCnt"), - new CaseBuilder() - .when(labelingAssignmentEntity.workState.eq("DONE")) - .then(1L) - .otherwise(0L) - .sum() - .as("doneCnt"), - new CaseBuilder() - .when(labelingAssignmentEntity.workState.eq("SKIP")) - .then(1L) - .otherwise(0L) - .sum() - .as("skipCnt"), - new CaseBuilder() - .when(labelingAssignmentEntity.workState.eq("DONE") - .and( - Expressions.stringTemplate( - "to_char({0}, 'YYYY-MM-DD')", labelingAssignmentEntity.modifiedDate).eq(s3) ) - ) - .then(1L) - .otherwise(0L) - .sum() - .as("day3AgoDoneCnt"), - new CaseBuilder() - .when(labelingAssignmentEntity.workState.eq("DONE") - .and( - Expressions.stringTemplate( - "to_char({0}, 'YYYY-MM-DD')", labelingAssignmentEntity.modifiedDate).eq(s2) ) - ) - .then(1L) - .otherwise(0L) - .sum() - .as("day2AgoDoneCnt"), - new CaseBuilder() - .when(labelingAssignmentEntity.workState.eq("DONE") - .and( - Expressions.stringTemplate( - "to_char({0}, 'YYYY-MM-DD')", labelingAssignmentEntity.modifiedDate).eq(s1) ) - ) - .then(1L) - .otherwise(0L) - .sum() - .as("day1AgoDoneCnt") - )) - .from(labelingAssignmentEntity) - .innerJoin(memberEntity) - .on(whereSubBuilder) - .where(whereBuilder) - .groupBy( - memberEntity.userRole, - memberEntity.name, - memberEntity.userId) - .offset(pageable.getOffset()) - .limit(pageable.getPageSize()) - .fetch(); + queryFactory + .select( + Projections.constructor( + WorkerState.class, + memberEntity.userRole, + memberEntity.name, + memberEntity.userId, + labelingAssignmentEntity.workerUid.count().as("assignedCnt"), + new CaseBuilder() + .when(labelingAssignmentEntity.workState.eq("DONE")) + .then(1L) + .otherwise(0L) + .sum() + .as("doneCnt"), + new CaseBuilder() + .when(labelingAssignmentEntity.workState.eq("SKIP")) + .then(1L) + .otherwise(0L) + .sum() + .as("skipCnt"), + new CaseBuilder() + .when( + labelingAssignmentEntity + .workState + .eq("DONE") + .and( + Expressions.stringTemplate( + "to_char({0}, 'YYYY-MM-DD')", + labelingAssignmentEntity.modifiedDate) + .eq(s3))) + .then(1L) + .otherwise(0L) + .sum() + .as("day3AgoDoneCnt"), + new CaseBuilder() + .when( + labelingAssignmentEntity + .workState + .eq("DONE") + .and( + Expressions.stringTemplate( + "to_char({0}, 'YYYY-MM-DD')", + labelingAssignmentEntity.modifiedDate) + .eq(s2))) + .then(1L) + .otherwise(0L) + .sum() + .as("day2AgoDoneCnt"), + new CaseBuilder() + .when( + labelingAssignmentEntity + .workState + .eq("DONE") + .and( + Expressions.stringTemplate( + "to_char({0}, 'YYYY-MM-DD')", + labelingAssignmentEntity.modifiedDate) + .eq(s1))) + .then(1L) + .otherwise(0L) + .sum() + .as("day1AgoDoneCnt"))) + .from(labelingAssignmentEntity) + .innerJoin(memberEntity) + .on(whereSubBuilder) + .where(whereBuilder) + .groupBy(memberEntity.userRole, memberEntity.name, memberEntity.userId) + .offset(pageable.getOffset()) + .limit(pageable.getPageSize()) + .fetch(); /* Long countQuery = @@ -376,6 +372,4 @@ public class LabelWorkRepositoryImpl extends QuerydslRepositorySupport mapSheetAnalInferenceEntity.createdDttm) .fetchOne(); } - - } From 053d33731432105aa0e660987b539a7286abbd1a Mon Sep 17 00:00:00 2001 From: DanielLee <198891672+sanghyeonhd@users.noreply.github.com> Date: Mon, 5 Jan 2026 13:41:32 +0900 Subject: [PATCH 4/6] build error fix # Conflicts: # src/main/java/com/kamco/cd/kamcoback/label/service/LabelAllocateService.java --- .../label/service/LabelAllocateService.java | 95 ++++++------------- 1 file changed, 29 insertions(+), 66 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 486065ab..a7864eaa 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 @@ -9,9 +9,7 @@ import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.LabelerDetail; 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; -import com.kamco.cd.kamcoback.label.dto.WorkerStatsDto.WorkerStatistics; import com.kamco.cd.kamcoback.postgres.core.LabelAllocateCoreService; -import java.time.LocalDate; import java.util.List; import java.util.Objects; import lombok.extern.slf4j.Slf4j; @@ -23,9 +21,6 @@ import org.springframework.transaction.annotation.Transactional; @Transactional public class LabelAllocateService { - private static final int STAGNATION_THRESHOLD = 10; // 정체 판단 기준 (3일 평균 처리량) - private static final int BATCH_SIZE = 100; // 배정 배치 크기 - private final LabelAllocateCoreService labelAllocateCoreService; public LabelAllocateService(LabelAllocateCoreService labelAllocateCoreService) { @@ -35,22 +30,22 @@ public class LabelAllocateService { /** * 도엽 기준 asc sorting 해서 할당 수만큼 배정하는 로직 * - * @param stage 회차 - * @param targetUsers 라벨러 목록 + * @param stage 회차 + * @param targetUsers 라벨러 목록 * @param targetInspectors 검수자 목록 */ @Transactional public ApiResponseDto.ResponseObj allocateAsc( - Integer stage, - List targetUsers, - List targetInspectors, - Integer compareYyyy, - Integer targetYyyy) { + Integer stage, + List targetUsers, + List targetInspectors, + Integer compareYyyy, + Integer targetYyyy) { Long lastId = null; // geom 잔여건수 조회 Long chargeCnt = - labelAllocateCoreService.findLabelUnAssignedCnt(stage, compareYyyy, targetYyyy); + labelAllocateCoreService.findLabelUnAssignedCnt(stage, compareYyyy, targetYyyy); if (chargeCnt <= 0) { return new ApiResponseDto.ResponseObj(ApiResponseCode.DUPLICATE_DATA, "이미 배정완료된 회차 입니다."); } @@ -58,15 +53,15 @@ public class LabelAllocateService { Long totalDemand = targetUsers.stream().mapToLong(TargetUser::getDemand).sum(); if (!Objects.equals(chargeCnt, totalDemand)) { return new ApiResponseDto.ResponseObj( - ApiResponseCode.BAD_REQUEST, "총 잔여건수와 요청 값의 합계가 맞지 않습니다."); + ApiResponseCode.BAD_REQUEST, "총 잔여건수와 요청 값의 합계가 맞지 않습니다."); } List allIds = - labelAllocateCoreService.fetchNextIds(lastId, chargeCnt, compareYyyy, targetYyyy, stage); + labelAllocateCoreService.fetchNextIds(lastId, chargeCnt, compareYyyy, targetYyyy, stage); // MapSheetAnalInferenceEntity analUid 가져오기 Long analUid = - labelAllocateCoreService.findMapSheetAnalInferenceUid(compareYyyy, targetYyyy, stage); + labelAllocateCoreService.findMapSheetAnalInferenceUid(compareYyyy, targetYyyy, stage); int index = 0; for (TargetUser target : targetUsers) { @@ -112,16 +107,17 @@ public class LabelAllocateService { /** * 작업자 통계 조회 * - * @param analUid 분석 ID + * @param analUid 분석 ID * @param workerType 작업자 유형 (LABELER/INSPECTOR) - * @param search 검색어 (이름 또는 사번) - * @param sortType 정렬 조건 - * @param page 페이지 번호 (0부터 시작) - * @param size 페이지 크기 + * @param search 검색어 (이름 또는 사번) + * @param sortType 정렬 조건 * @return 작업자 목록 및 통계 */ public WorkerListResponse getWorkerStatistics( - Long analUid, String workerType, String search, String sortType, Integer page, Integer size) { + Long analUid, + String workerType, + String search, + String sortType) { // 프로젝트 정보 조회 (analUid가 있을 때만) var projectInfo = labelAllocateCoreService.findProjectInfo(analUid); @@ -129,44 +125,10 @@ public class LabelAllocateService { // 작업 진행 현황 조회 var progressInfo = labelAllocateCoreService.findWorkProgressInfo(analUid); - // 작업자 통계 조회 - List workers = - labelAllocateCoreService.findWorkerStatistics(analUid, workerType, search, sortType); - - // 각 작업자별 3일치 처리량 조회 - LocalDate today = LocalDate.now(); - for (WorkerStatistics worker : workers) { - Long day1Count = - labelAllocateCoreService.findDailyProcessedCount( - worker.getWorkerId(), workerType, today.minusDays(1), analUid); - Long day2Count = - labelAllocateCoreService.findDailyProcessedCount( - worker.getWorkerId(), workerType, today.minusDays(2), analUid); - Long day3Count = - labelAllocateCoreService.findDailyProcessedCount( - worker.getWorkerId(), workerType, today.minusDays(3), analUid); - - long average = (day1Count + day2Count + day3Count) / 3; - } - - // 페이징 처리 - long totalElements = workers.size(); - int totalPages = (int) Math.ceil((double) totalElements / size); - int fromIndex = page * size; - int toIndex = Math.min(fromIndex + size, workers.size()); - - List pagedWorkers = - (fromIndex < workers.size()) ? workers.subList(fromIndex, toIndex) : List.of(); - return WorkerListResponse.builder() - .projectInfo(projectInfo) - .progressInfo(progressInfo) - .workers(pagedWorkers) - .currentPage(page) - .pageSize(size) - .totalElements(totalElements) - .totalPages(totalPages) - .build(); + .projectInfo(projectInfo) + .progressInfo(progressInfo) + .build(); } public InferenceDetail findInferenceDetail(String uuid) { @@ -174,11 +136,12 @@ public class LabelAllocateService { } public ApiResponseDto.ResponseObj allocateMove( - Integer stage, - List targetUsers, - Integer compareYyyy, - Integer targetYyyy, - String userId) { + String autoType, + Integer stage, + List targetUsers, + Integer compareYyyy, + Integer targetYyyy, + String userId) { Long lastId = null; Long chargeCnt = targetUsers.stream().mapToLong(TargetUser::getDemand).sum(); @@ -188,8 +151,8 @@ public class LabelAllocateService { } List allIds = - labelAllocateCoreService.fetchNextMoveIds( - lastId, chargeCnt, compareYyyy, targetYyyy, stage, userId); + labelAllocateCoreService.fetchNextMoveIds( + lastId, chargeCnt, compareYyyy, targetYyyy, stage, userId); int index = 0; for (TargetUser target : targetUsers) { int end = index + target.getDemand(); From 7acfd32b498eeee947a7363778ba72193b6ee889 Mon Sep 17 00:00:00 2001 From: "gayoun.park" Date: Mon, 5 Jan 2026 14:54:42 +0900 Subject: [PATCH 5/6] merge --- .../label/service/LabelAllocateService.java | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 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 a7864eaa..4581c2af 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 @@ -6,6 +6,7 @@ import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto; 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.TargetUser; import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.UserList; import com.kamco.cd.kamcoback.label.dto.WorkerStatsDto.WorkerListResponse; @@ -13,6 +14,7 @@ import com.kamco.cd.kamcoback.postgres.core.LabelAllocateCoreService; import java.util.List; import java.util.Objects; import lombok.extern.slf4j.Slf4j; +import org.springframework.data.domain.Page; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -136,7 +138,6 @@ public class LabelAllocateService { } public ApiResponseDto.ResponseObj allocateMove( - String autoType, Integer stage, List targetUsers, Integer compareYyyy, @@ -165,7 +166,20 @@ public class LabelAllocateService { return new ApiResponseDto.ResponseObj(ApiResponseCode.OK, "이관을 완료하였습니다."); } - public LabelerDetail findLabelerDetail(String userId, String uuid) { - return labelAllocateCoreService.findLabelerDetail(userId, uuid); + public LabelerDetail findUserDetail(String userId, String uuid, String type) { + if (type.equals("LABELER")) { + return labelAllocateCoreService.findLabelerDetail(userId, uuid); + } else { + return labelAllocateCoreService.findInspectorDetail(userId, uuid); + } + } + + public Page findDaliyList( + LabelAllocateDto.searchReq searchReq, String uuid, String userId, String type) { + if (type.equals("LABELER")) { + return labelAllocateCoreService.findLabelerDailyStat(searchReq, uuid, userId); + } else { + return labelAllocateCoreService.findInspectorDailyStat(searchReq, uuid, userId); + } } } From 067862ff121afdb553331391146fe4449056f127 Mon Sep 17 00:00:00 2001 From: teddy Date: Mon, 5 Jan 2026 15:01:51 +0900 Subject: [PATCH 6/6] =?UTF-8?q?=EB=9D=BC=EB=B2=A8=EB=A7=81=EC=9E=91?= =?UTF-8?q?=EC=97=85=20=EA=B4=80=EB=A6=AC=20=EB=AA=A9=EB=A1=9D=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../label/service/LabelAllocateService.java | 54 +++++++++---------- .../label/LabelWorkRepositoryImpl.java | 23 ++++---- 2 files changed, 36 insertions(+), 41 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 4581c2af..fa850685 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 @@ -32,22 +32,22 @@ public class LabelAllocateService { /** * 도엽 기준 asc sorting 해서 할당 수만큼 배정하는 로직 * - * @param stage 회차 - * @param targetUsers 라벨러 목록 + * @param stage 회차 + * @param targetUsers 라벨러 목록 * @param targetInspectors 검수자 목록 */ @Transactional public ApiResponseDto.ResponseObj allocateAsc( - Integer stage, - List targetUsers, - List targetInspectors, - Integer compareYyyy, - Integer targetYyyy) { + Integer stage, + List targetUsers, + List targetInspectors, + Integer compareYyyy, + Integer targetYyyy) { Long lastId = null; // geom 잔여건수 조회 Long chargeCnt = - labelAllocateCoreService.findLabelUnAssignedCnt(stage, compareYyyy, targetYyyy); + labelAllocateCoreService.findLabelUnAssignedCnt(stage, compareYyyy, targetYyyy); if (chargeCnt <= 0) { return new ApiResponseDto.ResponseObj(ApiResponseCode.DUPLICATE_DATA, "이미 배정완료된 회차 입니다."); } @@ -55,15 +55,15 @@ public class LabelAllocateService { Long totalDemand = targetUsers.stream().mapToLong(TargetUser::getDemand).sum(); if (!Objects.equals(chargeCnt, totalDemand)) { return new ApiResponseDto.ResponseObj( - ApiResponseCode.BAD_REQUEST, "총 잔여건수와 요청 값의 합계가 맞지 않습니다."); + ApiResponseCode.BAD_REQUEST, "총 잔여건수와 요청 값의 합계가 맞지 않습니다."); } List allIds = - labelAllocateCoreService.fetchNextIds(lastId, chargeCnt, compareYyyy, targetYyyy, stage); + labelAllocateCoreService.fetchNextIds(lastId, chargeCnt, compareYyyy, targetYyyy, stage); // MapSheetAnalInferenceEntity analUid 가져오기 Long analUid = - labelAllocateCoreService.findMapSheetAnalInferenceUid(compareYyyy, targetYyyy, stage); + labelAllocateCoreService.findMapSheetAnalInferenceUid(compareYyyy, targetYyyy, stage); int index = 0; for (TargetUser target : targetUsers) { @@ -109,17 +109,14 @@ public class LabelAllocateService { /** * 작업자 통계 조회 * - * @param analUid 분석 ID + * @param analUid 분석 ID * @param workerType 작업자 유형 (LABELER/INSPECTOR) - * @param search 검색어 (이름 또는 사번) - * @param sortType 정렬 조건 + * @param search 검색어 (이름 또는 사번) + * @param sortType 정렬 조건 * @return 작업자 목록 및 통계 */ public WorkerListResponse getWorkerStatistics( - Long analUid, - String workerType, - String search, - String sortType) { + Long analUid, String workerType, String search, String sortType) { // 프로젝트 정보 조회 (analUid가 있을 때만) var projectInfo = labelAllocateCoreService.findProjectInfo(analUid); @@ -127,10 +124,7 @@ public class LabelAllocateService { // 작업 진행 현황 조회 var progressInfo = labelAllocateCoreService.findWorkProgressInfo(analUid); - return WorkerListResponse.builder() - .projectInfo(projectInfo) - .progressInfo(progressInfo) - .build(); + return WorkerListResponse.builder().projectInfo(projectInfo).progressInfo(progressInfo).build(); } public InferenceDetail findInferenceDetail(String uuid) { @@ -138,11 +132,11 @@ public class LabelAllocateService { } public ApiResponseDto.ResponseObj allocateMove( - Integer stage, - List targetUsers, - Integer compareYyyy, - Integer targetYyyy, - String userId) { + Integer stage, + List targetUsers, + Integer compareYyyy, + Integer targetYyyy, + String userId) { Long lastId = null; Long chargeCnt = targetUsers.stream().mapToLong(TargetUser::getDemand).sum(); @@ -152,8 +146,8 @@ public class LabelAllocateService { } List allIds = - labelAllocateCoreService.fetchNextMoveIds( - lastId, chargeCnt, compareYyyy, targetYyyy, stage, userId); + labelAllocateCoreService.fetchNextMoveIds( + lastId, chargeCnt, compareYyyy, targetYyyy, stage, userId); int index = 0; for (TargetUser target : targetUsers) { int end = index + target.getDemand(); @@ -175,7 +169,7 @@ public class LabelAllocateService { } public Page findDaliyList( - LabelAllocateDto.searchReq searchReq, String uuid, String userId, String type) { + LabelAllocateDto.searchReq searchReq, String uuid, String userId, String type) { if (type.equals("LABELER")) { return labelAllocateCoreService.findLabelerDailyStat(searchReq, uuid, userId); } else { diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/label/LabelWorkRepositoryImpl.java b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/label/LabelWorkRepositoryImpl.java index dbc1d4cb..fc27a3c8 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/label/LabelWorkRepositoryImpl.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/label/LabelWorkRepositoryImpl.java @@ -314,18 +314,19 @@ public class LabelWorkRepositoryImpl extends QuerydslRepositorySupport .fetchOne(); */ - Long total = - queryFactory - .select(mapSheetAnalInferenceEntity.uuid.countDistinct()) - .from(mapSheetAnalInferenceEntity) - .innerJoin(mapSheetAnalDataInferenceEntity) - .on(whereSubDataBuilder) - .innerJoin(mapSheetAnalDataInferenceGeomEntity) - .on(whereSubBuilder) - .where(whereBuilder) - .fetchOne(); + Long totalCnt = + (long) + queryFactory + .select(memberEntity.userRole, memberEntity.name, memberEntity.userId) + .from(labelingAssignmentEntity) + .innerJoin(memberEntity) + .on(whereSubBuilder) + .where(whereBuilder) + .groupBy(memberEntity.userRole, memberEntity.name, memberEntity.userId) + .fetch() + .size(); - return new PageImpl<>(foundContent, pageable, total); + return new PageImpl<>(foundContent, pageable, totalCnt); } /**