From cc5015213b5dd80a31e30faba2da4cb6fc85ecd8 Mon Sep 17 00:00:00 2001 From: Moon Date: Fri, 2 Jan 2026 20:59:19 +0900 Subject: [PATCH] =?UTF-8?q?=EB=9D=BC=EB=B2=A8=EB=A7=81=EC=9E=91=EC=97=85?= =?UTF-8?q?=EA=B4=80=EB=A6=AC=20=EB=A6=AC=EC=8A=A4=ED=8A=B8=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../label/LabelWorkerApiController.java | 60 +++++++ .../cd/kamcoback/label/dto/LabelWorkDto.java | 102 ++++++++++++ .../label/service/LabelWorkService.java | 34 ++++ .../postgres/core/LabelWorkCoreService.java | 31 ++++ .../repository/label/LabelWorkRepository.java | 8 + .../label/LabelWorkRepositoryCustom.java | 14 ++ .../label/LabelWorkRepositoryImpl.java | 157 ++++++++++++++++++ 7 files changed, 406 insertions(+) create mode 100644 src/main/java/com/kamco/cd/kamcoback/label/LabelWorkerApiController.java create mode 100644 src/main/java/com/kamco/cd/kamcoback/label/dto/LabelWorkDto.java create mode 100644 src/main/java/com/kamco/cd/kamcoback/label/service/LabelWorkService.java create mode 100644 src/main/java/com/kamco/cd/kamcoback/postgres/core/LabelWorkCoreService.java create mode 100644 src/main/java/com/kamco/cd/kamcoback/postgres/repository/label/LabelWorkRepository.java create mode 100644 src/main/java/com/kamco/cd/kamcoback/postgres/repository/label/LabelWorkRepositoryCustom.java create mode 100644 src/main/java/com/kamco/cd/kamcoback/postgres/repository/label/LabelWorkRepositoryImpl.java diff --git a/src/main/java/com/kamco/cd/kamcoback/label/LabelWorkerApiController.java b/src/main/java/com/kamco/cd/kamcoback/label/LabelWorkerApiController.java new file mode 100644 index 00000000..9314910b --- /dev/null +++ b/src/main/java/com/kamco/cd/kamcoback/label/LabelWorkerApiController.java @@ -0,0 +1,60 @@ +package com.kamco.cd.kamcoback.label; + +import com.kamco.cd.kamcoback.code.dto.CommonCodeDto; +import com.kamco.cd.kamcoback.config.api.ApiResponseDto; +import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto; +import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.TargetInspector; +import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.TargetUser; +import com.kamco.cd.kamcoback.label.dto.LabelWorkDto; +import com.kamco.cd.kamcoback.label.dto.LabelWorkDto.LabelWorkMng; +import com.kamco.cd.kamcoback.label.service.LabelAllocateService; +import com.kamco.cd.kamcoback.label.service.LabelWorkService; +import com.kamco.cd.kamcoback.mapsheet.dto.MapSheetMngDto; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import java.util.List; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.data.domain.Page; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +@Slf4j +@Tag(name = "라벨링 작업 관리", description = "라벨링 작업 관리") +@RequestMapping({"/api/label"}) +@RequiredArgsConstructor +@RestController +public class LabelWorkerApiController { + + private final LabelWorkService labelWorkService; + + @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) + }) + @PostMapping("/label-work-mng-list") + public ApiResponseDto> labelWorkMngList( + @RequestBody @Valid LabelWorkDto.LabelWorkMngSearchReq searchReq) { + return ApiResponseDto.ok(labelWorkService.labelWorkMngList(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 new file mode 100644 index 00000000..cd3d7d6e --- /dev/null +++ b/src/main/java/com/kamco/cd/kamcoback/label/dto/LabelWorkDto.java @@ -0,0 +1,102 @@ +package com.kamco.cd.kamcoback.label.dto; + +import com.kamco.cd.kamcoback.common.enums.MngStateType; +import com.kamco.cd.kamcoback.common.utils.enums.CodeExpose; +import com.kamco.cd.kamcoback.common.utils.enums.EnumType; +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 io.swagger.v3.oas.annotations.media.Schema; +import java.time.ZonedDateTime; +import java.util.UUID; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; + +public class LabelWorkDto { + + + + @Schema(name = "LabelWorkMng", description = "라벨작업관리") + @Getter + @Setter + @NoArgsConstructor + @AllArgsConstructor + public static class LabelWorkMng { + + private int compareYyyy; + private int targetYyyy; + private int stage; + @JsonFormatDttm private ZonedDateTime createdDttm; + private Long detectionTotCnt; + private Long labelTotCnt; + private Long labelStopTotCnt; + private Long labelIngTotCnt; + private Long labelCompleteTotCnt; + @JsonFormatDttm private ZonedDateTime labelStartDttm; + + + public String getLabelState() { + + String mngState = "PENDING"; + + if (this.labelTotCnt == 0) mngState = "PENDING"; + else if (this.labelIngTotCnt > 0) mngState = "LABEL_ING"; + else if (this.labelTotCnt <= labelCompleteTotCnt) mngState = "LABEL_COMPLETE"; + + return mngState; + } + + public String getLabelStateName() { + String enumId = this.getLabelState(); + if (enumId == null || enumId.isEmpty()) { + enumId = "PENDING"; + } + + LabelMngState type = Enums.fromId(LabelMngState.class, enumId); + return type.getText(); + } + + public double getLabelRate() { + if (this.labelTotCnt == null || this.labelCompleteTotCnt == 0) { + return 0.0; + } + return (double) this.labelTotCnt / this.labelCompleteTotCnt * 100.0; + } + } + + + @Schema(name = "LabelWorkMngSearchReq", description = "라벨작업관리 검색 요청") + @Getter + @Setter + @NoArgsConstructor + @AllArgsConstructor + public static class LabelWorkMngSearchReq { + + // 페이징 파라미터 + @Schema(description = "페이지 번호 (0부터 시작) ", example = "0") + private int page = 0; + + @Schema(description = "페이지 크기", example = "20") + private int size = 20; + + @Schema(description = "변화탐지년도", example = "2024") + private Integer detectYyyy; + + @Schema(description = "시작일", example = "20240101") + private String strtDttm; + + @Schema(description = "종료일", example = "20241201") + private String endDttm; + + public Pageable toPageable() { + + return PageRequest.of(page, size); + } + } + +} 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 new file mode 100644 index 00000000..a16d447b --- /dev/null +++ b/src/main/java/com/kamco/cd/kamcoback/label/service/LabelWorkService.java @@ -0,0 +1,34 @@ +package com.kamco.cd.kamcoback.label.service; + +import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto; +import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.TargetInspector; +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.LabelWorkDto; +import com.kamco.cd.kamcoback.label.dto.LabelWorkDto.LabelWorkMng; +import com.kamco.cd.kamcoback.postgres.core.LabelAllocateCoreService; +import com.kamco.cd.kamcoback.postgres.core.LabelWorkCoreService; +import jakarta.transaction.Transactional; +import java.util.List; +import java.util.Objects; +import lombok.extern.slf4j.Slf4j; +import org.springframework.data.domain.Page; +import org.springframework.stereotype.Service; + +@Slf4j +@Service +public class LabelWorkService { + + private final LabelWorkCoreService labelWorkCoreService; + + public LabelWorkService(LabelWorkCoreService labelWorkCoreService) { + this.labelWorkCoreService = labelWorkCoreService; + } + + + + public Page labelWorkMngList(LabelWorkDto.LabelWorkMngSearchReq searchReq) { + + return labelWorkCoreService.labelWorkMngList(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 new file mode 100644 index 00000000..9c87a7be --- /dev/null +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/core/LabelWorkCoreService.java @@ -0,0 +1,31 @@ +package com.kamco.cd.kamcoback.postgres.core; + +import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto; +import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.UserList; +import com.kamco.cd.kamcoback.label.dto.LabelWorkDto; +import com.kamco.cd.kamcoback.label.dto.LabelWorkDto.LabelWorkMng; +import com.kamco.cd.kamcoback.mapsheet.dto.MapSheetMngDto; +import com.kamco.cd.kamcoback.mapsheet.dto.MapSheetMngDto.ErrorDataDto; +import com.kamco.cd.kamcoback.postgres.entity.LabelingAssignmentEntity; +import com.kamco.cd.kamcoback.postgres.repository.label.LabelAllocateRepository; +import com.kamco.cd.kamcoback.postgres.repository.label.LabelWorkRepository; +import jakarta.validation.Valid; +import java.util.List; +import java.util.UUID; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class LabelWorkCoreService { + + private final LabelWorkRepository labelWorkRepository; + + + public Page labelWorkMngList(LabelWorkDto.LabelWorkMngSearchReq searchReq) { + return labelWorkRepository.labelWorkMngList(searchReq); + } + + +} diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/label/LabelWorkRepository.java b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/label/LabelWorkRepository.java new file mode 100644 index 00000000..f094d50a --- /dev/null +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/label/LabelWorkRepository.java @@ -0,0 +1,8 @@ +package com.kamco.cd.kamcoback.postgres.repository.label; + +import com.kamco.cd.kamcoback.postgres.entity.MapSheetAnalDataInferenceGeomEntity; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface LabelWorkRepository + extends JpaRepository, + LabelWorkRepositoryCustom {} 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 new file mode 100644 index 00000000..37a0e289 --- /dev/null +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/label/LabelWorkRepositoryCustom.java @@ -0,0 +1,14 @@ +package com.kamco.cd.kamcoback.postgres.repository.label; + +import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.UserList; +import com.kamco.cd.kamcoback.label.dto.LabelWorkDto; +import com.kamco.cd.kamcoback.label.dto.LabelWorkDto.LabelWorkMng; +import com.kamco.cd.kamcoback.postgres.entity.LabelingAssignmentEntity; +import java.util.List; +import java.util.UUID; +import org.springframework.data.domain.Page; + +public interface LabelWorkRepositoryCustom { + + public Page labelWorkMngList(LabelWorkDto.LabelWorkMngSearchReq 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 new file mode 100644 index 00000000..a7e1c3fa --- /dev/null +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/label/LabelWorkRepositoryImpl.java @@ -0,0 +1,157 @@ +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.QMapSheetAnalEntity.mapSheetAnalEntity; +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.LabelAllocateDto.LabelState; +import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.UserList; +import com.kamco.cd.kamcoback.label.dto.LabelWorkDto; +import com.kamco.cd.kamcoback.label.dto.LabelWorkDto.LabelWorkMng; +import com.kamco.cd.kamcoback.mapsheet.dto.MapSheetMngDto; +import com.kamco.cd.kamcoback.mapsheet.dto.MapSheetMngDto.ErrorDataDto; +import com.kamco.cd.kamcoback.postgres.entity.LabelingAssignmentEntity; +import com.kamco.cd.kamcoback.postgres.entity.MapSheetAnalDataGeomEntity; +import com.kamco.cd.kamcoback.postgres.entity.MapSheetAnalEntity; +import com.querydsl.core.BooleanBuilder; +import com.querydsl.core.types.Projections; +import com.querydsl.core.types.dsl.CaseBuilder; +import com.querydsl.core.types.dsl.Expressions; +import com.querydsl.core.types.dsl.StringExpression; +import com.querydsl.jpa.impl.JPAQueryFactory; +import jakarta.persistence.EntityManager; +import jakarta.persistence.EntityNotFoundException; +import jakarta.persistence.PersistenceContext; +import jakarta.validation.Valid; +import java.time.LocalDate; +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 lombok.extern.slf4j.Slf4j; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.support.QuerydslRepositorySupport; +import org.springframework.stereotype.Repository; + +@Slf4j +@Repository +public class LabelWorkRepositoryImpl extends QuerydslRepositorySupport + implements LabelWorkRepositoryCustom { + + private final JPAQueryFactory queryFactory; + private final StringExpression NULL_STRING = Expressions.stringTemplate("cast(null as text)"); + + @PersistenceContext private EntityManager em; + + public LabelWorkRepositoryImpl(JPAQueryFactory queryFactory) { + super(MapSheetAnalDataGeomEntity.class); + this.queryFactory = queryFactory; + } + + + @Override + public Page labelWorkMngList(LabelWorkDto.LabelWorkMngSearchReq searchReq) { + + Pageable pageable = PageRequest.of(searchReq.getPage(), searchReq.getSize()); + BooleanBuilder whereBuilder = new BooleanBuilder(); + BooleanBuilder whereSubBuilder = new BooleanBuilder(); + + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd"); + + if (searchReq.getDetectYyyy() != null) { + whereBuilder.and(mapSheetAnalDataInferenceEntity.targetYyyy.eq(searchReq.getDetectYyyy())); + } + + //mapSheetAnalDataInferenceGeomEntity.dataUid.eq(mapSheetAnalDataInferenceEntity.id) + + whereSubBuilder.and(mapSheetAnalDataInferenceGeomEntity.dataUid.eq(mapSheetAnalDataInferenceEntity.id)); + + if (searchReq.getStrtDttm() != null && ! searchReq.getStrtDttm().isEmpty()) { + + whereSubBuilder.and(mapSheetAnalDataInferenceGeomEntity.labelStateDttm.isNotNull()); + + whereSubBuilder.and( + Expressions.stringTemplate("to_char({0}, 'YYYY-MM-DD')", mapSheetAnalDataInferenceEntity.labelStateDttm) + .gt("2024-01-01") + ); + } + + + + List foundContent = + queryFactory + .select( + Projections.constructor( + LabelWorkMng.class, + mapSheetAnalDataInferenceEntity.compareYyyy, + mapSheetAnalDataInferenceEntity.targetYyyy, + mapSheetAnalDataInferenceEntity.stage, + mapSheetAnalDataInferenceEntity.createdDttm.min(), + mapSheetAnalDataInferenceEntity.detectingCnt.sum(), + mapSheetAnalDataInferenceGeomEntity.dataUid.count(), + + new CaseBuilder() + .when(mapSheetAnalDataInferenceGeomEntity.labelState.eq("STOP")) + .then(1L) + .otherwise(0L) + .sum(), + new CaseBuilder() + .when(mapSheetAnalDataInferenceGeomEntity.labelState.eq("LABEL_ING")) + .then(1L) + .otherwise(0L) + .sum(), + new CaseBuilder() + .when(mapSheetAnalDataInferenceGeomEntity.labelState.eq("LABEL_COMPLETE")) + .then(1L) + .otherwise(0L) + .sum(), + + mapSheetAnalDataInferenceGeomEntity.labelStateDttm.min() + )) + .from(mapSheetAnalDataInferenceEntity) + .leftJoin(mapSheetAnalDataInferenceGeomEntity) + .on(whereSubBuilder) + .where(whereBuilder) + .groupBy( + mapSheetAnalDataInferenceEntity.compareYyyy, + mapSheetAnalDataInferenceEntity.targetYyyy, + mapSheetAnalDataInferenceEntity.stage + ) + .orderBy(mapSheetAnalDataInferenceEntity.targetYyyy.desc() + ,mapSheetAnalDataInferenceEntity.stage.desc()) + .offset(pageable.getOffset()) + .limit(pageable.getPageSize()) + .fetch(); + + /* + Long countQuery = + queryFactory + .select(mapSheetAnalDataInferenceEntity.count()) + .from(mapSheetAnalDataInferenceEntity) + .leftJoin(mapSheetAnalDataInferenceGeomEntity) + .on(whereSubBuilder) + .where(whereBuilder) + .groupBy( + mapSheetAnalDataInferenceEntity.compareYyyy, + mapSheetAnalDataInferenceEntity.targetYyyy, + mapSheetAnalDataInferenceEntity.stage + ) + .fetchOne(); + + */ + + Long countQuery = foundContent.stream().count(); + + return new PageImpl<>(foundContent, pageable, countQuery); + } +}