Merge pull request 'feat/infer_dev_260107' (#164) from feat/infer_dev_260107 into develop
Reviewed-on: https://kamco.gitea.gs.dabeeo.com/dabeeo/kamco-dabeeo-backoffice/pulls/164
This commit is contained in:
@@ -64,9 +64,10 @@ public class InferenceResultDto {
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum MapSheetScope implements EnumType {
|
||||
EXCL("추론제외"),
|
||||
PREV("이전 년도 도엽 사용"),
|
||||
ALL("전체"),
|
||||
PART("부분"),
|
||||
;
|
||||
|
||||
private final String desc;
|
||||
|
||||
@Override
|
||||
@@ -84,8 +85,8 @@ public class InferenceResultDto {
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum DetectOption implements EnumType {
|
||||
ALL("전체"),
|
||||
PART("부분"),
|
||||
EXCL("추론제외"),
|
||||
PREV("이전 년도 도엽 사용"),
|
||||
;
|
||||
private final String desc;
|
||||
|
||||
@@ -131,16 +132,16 @@ public class InferenceResultDto {
|
||||
@NotNull
|
||||
private Integer targetYyyy;
|
||||
|
||||
@Schema(description = "분석대상 도엽 - 전체(ALL), 부분(PART)", example = "PART")
|
||||
@NotBlank
|
||||
@EnumValid(enumClass = DetectOption.class, message = "분석대상 도엽 옵션은 '전체', '부분' 만 사용 가능합니다.")
|
||||
private String mapSheetScope;
|
||||
|
||||
@Schema(description = "탐지 데이터 옵션 - 추론제외(PREV), 이전 년도 도엽 사용(PREV)", example = "EXCL")
|
||||
@NotBlank
|
||||
@EnumValid(
|
||||
enumClass = MapSheetScope.class,
|
||||
message = "탐지 데이터 옵션은 '추론제외', '이전 년도 도엽 사용' 만 사용 가능합니다.")
|
||||
private String mapSheetScope;
|
||||
|
||||
@Schema(description = "분석대상 도엽 - 전체(ALL), 부분(PART)", example = "PART")
|
||||
@NotBlank
|
||||
@EnumValid(enumClass = DetectOption.class, message = "분석대상 도엽 옵션은 '전체', '부분' 만 사용 가능합니다.")
|
||||
private String detectOption;
|
||||
|
||||
@Schema(description = "5k 도협 번호 목록", example = "[34607067,34607067]")
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
package com.kamco.cd.kamcoback.label;
|
||||
|
||||
import com.kamco.cd.kamcoback.common.enums.RoleType;
|
||||
import com.kamco.cd.kamcoback.config.api.ApiResponseDto;
|
||||
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.WorkerStatsDto.UpdateClosedRequest;
|
||||
import com.kamco.cd.kamcoback.label.dto.WorkerStatsDto.WorkerListResponse;
|
||||
import com.kamco.cd.kamcoback.label.service.LabelAllocateService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
@@ -54,7 +54,9 @@ public class LabelAllocateApiController {
|
||||
return ApiResponseDto.ok(labelAllocateService.availUserList(role));
|
||||
}
|
||||
|
||||
@Operation(summary = "작업현황 관리 > 프로젝트 및 진행 상황 정보", description = "작업현황 관리 > 프로젝트 및 진행 상황 정보")
|
||||
@Operation(
|
||||
summary = "작업현황 관리 > 프로젝트 및 진행 상황 정보",
|
||||
description = "작업현황 관리 > 프로젝트 및 진행 상황 정보. UUID를 입력하면 해당 프로젝트 정보를 조회하고, 미입력 시 최신 프로젝트를 조회합니다.")
|
||||
@ApiResponses(
|
||||
value = {
|
||||
@ApiResponse(responseCode = "200", description = "조회 성공"),
|
||||
@@ -63,18 +65,18 @@ public class LabelAllocateApiController {
|
||||
})
|
||||
@GetMapping("/projectinfo")
|
||||
public ApiResponseDto<WorkerListResponse> getWorkerStatistics(
|
||||
// @Parameter(description = "분석 ID (선택)", example = "3") @RequestParam(required = false)
|
||||
// Long analUid,
|
||||
@Parameter(
|
||||
description = "작업자 유형 (선택) - 미입력 시 LABELER로 조회",
|
||||
description = "프로젝트 UUID (선택) - 미입력 시 최신 프로젝트 조회",
|
||||
example = "f97dc186-e6d3-4645-9737-3173dde8dc64")
|
||||
@RequestParam(required = false)
|
||||
String uuid,
|
||||
@Parameter(
|
||||
description = "작업자 유형 (선택) - 미입력 시 전체 조회",
|
||||
example = "LABELER",
|
||||
schema =
|
||||
@Schema(
|
||||
allowableValues = {"LABELER", "REVIEWER"},
|
||||
defaultValue = "LABELER"))
|
||||
schema = @Schema(allowableValues = {"LABELER", "REVIEWER"}))
|
||||
@RequestParam(required = false)
|
||||
String type,
|
||||
@Parameter(description = "검색어 (작업자 이름 또는 사번으로 검색, 부분 일치)", example = "김라벨")
|
||||
@Parameter(description = "검색어 (작업자 이름 또는 사번으로 검색, 부분 일치) - 미입력 시 전체 조회", example = "김라벨")
|
||||
@RequestParam(required = false)
|
||||
String search,
|
||||
@Parameter(
|
||||
@@ -94,11 +96,8 @@ public class LabelAllocateApiController {
|
||||
@RequestParam(required = false)
|
||||
String sort) {
|
||||
|
||||
// type이 null이면 기본값으로 LABELER 설정
|
||||
String workerType = (type == null || type.isEmpty()) ? RoleType.LABELER.name() : type;
|
||||
|
||||
return ApiResponseDto.ok(
|
||||
labelAllocateService.getWorkerStatistics(null, workerType, search, sort));
|
||||
labelAllocateService.getWorkerStatisticsByUuid(uuid, type, search, sort));
|
||||
}
|
||||
|
||||
@Operation(summary = "라벨링작업 관리 > 작업 배정", description = "라벨링작업 관리 > 작업 배정")
|
||||
@@ -236,4 +235,71 @@ public class LabelAllocateApiController {
|
||||
String uuid) {
|
||||
return ApiResponseDto.ok(labelAllocateService.moveAvailUserList(userId, uuid));
|
||||
}
|
||||
|
||||
@Operation(
|
||||
summary = "작업현황 관리 > 라벨링/검수 종료 여부 업데이트",
|
||||
description = "라벨링/검수 종료 여부를 업데이트합니다. uuid 생략 시 최신 프로젝트 대상")
|
||||
@ApiResponses(
|
||||
value = {
|
||||
@ApiResponse(responseCode = "200", description = "업데이트 성공"),
|
||||
@ApiResponse(responseCode = "400", description = "잘못된 요청 데이터", content = @Content),
|
||||
@ApiResponse(responseCode = "500", description = "서버 오류", content = @Content)
|
||||
})
|
||||
@PostMapping("/projectinfo/closed")
|
||||
public ApiResponseDto<ApiResponseDto.ResponseObj> updateClosedYn(
|
||||
@io.swagger.v3.oas.annotations.parameters.RequestBody(
|
||||
description = "종료 여부 업데이트 요청",
|
||||
required = true,
|
||||
content =
|
||||
@Content(
|
||||
mediaType = "application/json",
|
||||
schema = @Schema(implementation = UpdateClosedRequest.class),
|
||||
examples = {
|
||||
@io.swagger.v3.oas.annotations.media.ExampleObject(
|
||||
name = "라벨링 종료",
|
||||
value =
|
||||
"""
|
||||
{"closedType": "LABELING", "closedYn": "Y"}
|
||||
"""),
|
||||
@io.swagger.v3.oas.annotations.media.ExampleObject(
|
||||
name = "검수 종료",
|
||||
value =
|
||||
"""
|
||||
{"closedType": "INSPECTION", "closedYn": "Y"}
|
||||
"""),
|
||||
@io.swagger.v3.oas.annotations.media.ExampleObject(
|
||||
name = "라벨링 재개",
|
||||
value =
|
||||
"""
|
||||
{"closedType": "LABELING", "closedYn": "N"}
|
||||
"""),
|
||||
@io.swagger.v3.oas.annotations.media.ExampleObject(
|
||||
name = "검수 재개",
|
||||
value =
|
||||
"""
|
||||
{"closedType": "INSPECTION", "closedYn": "N"}
|
||||
"""),
|
||||
@io.swagger.v3.oas.annotations.media.ExampleObject(
|
||||
name = "특정 프로젝트 라벨링 종료",
|
||||
value =
|
||||
"""
|
||||
{"uuid": "f97dc186-e6d3-4645-9737-3173dde8dc64", "closedType": "LABELING", "closedYn": "Y"}
|
||||
""")
|
||||
}))
|
||||
@RequestBody
|
||||
@Valid
|
||||
UpdateClosedRequest request) {
|
||||
|
||||
labelAllocateService.updateClosedYn(
|
||||
request.getUuid(), request.getClosedType(), request.getClosedYn());
|
||||
|
||||
String typeLabel = "LABELING".equals(request.getClosedType()) ? "라벨링" : "검수";
|
||||
String statusMessage =
|
||||
"Y".equals(request.getClosedYn())
|
||||
? typeLabel + "이(가) 종료되었습니다."
|
||||
: typeLabel + "이(가) 재개되었습니다.";
|
||||
|
||||
return ApiResponseDto.okObject(
|
||||
new ApiResponseDto.ResponseObj(ApiResponseDto.ApiResponseCode.OK, statusMessage));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@ package com.kamco.cd.kamcoback.label.dto;
|
||||
|
||||
import com.kamco.cd.kamcoback.common.utils.interfaces.JsonFormatDttm;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.Pattern;
|
||||
import java.time.ZonedDateTime;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
@@ -35,6 +37,43 @@ public class WorkerStatsDto {
|
||||
|
||||
@Schema(description = "프로젝트 UUID")
|
||||
private String uuid;
|
||||
|
||||
@Schema(description = "라벨링 종료 여부 (Y: 종료, N: 진행중)")
|
||||
private String labelingClosedYn;
|
||||
|
||||
@Schema(description = "검수 종료 여부 (Y: 종료, N: 진행중)")
|
||||
private String inspectionClosedYn;
|
||||
}
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Schema(description = "프로젝트 종료 여부 업데이트 요청")
|
||||
public static class UpdateClosedRequest {
|
||||
|
||||
@Schema(
|
||||
description = "프로젝트 UUID (선택) - 미입력 시 현재 진행중인 최신 프로젝트가 대상",
|
||||
example = "f97dc186-e6d3-4645-9737-3173dde8dc64")
|
||||
private String uuid;
|
||||
|
||||
@NotBlank(message = "종료 유형은 필수입니다.")
|
||||
@Pattern(regexp = "^(LABELING|INSPECTION)$", message = "종료 유형은 LABELING 또는 INSPECTION이어야 합니다.")
|
||||
@Schema(
|
||||
description = "종료 유형 (LABELING: 라벨링, INSPECTION: 검수)",
|
||||
example = "LABELING",
|
||||
allowableValues = {"LABELING", "INSPECTION"},
|
||||
requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private String closedType;
|
||||
|
||||
@NotBlank(message = "종료 여부는 필수입니다.")
|
||||
@Pattern(regexp = "^[YN]$", message = "종료 여부는 Y 또는 N이어야 합니다.")
|
||||
@Schema(
|
||||
description = "종료 여부 (Y: 종료, N: 진행중)",
|
||||
example = "Y",
|
||||
allowableValues = {"Y", "N"},
|
||||
requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private String closedYn;
|
||||
}
|
||||
|
||||
@Getter
|
||||
@@ -144,7 +183,7 @@ public class WorkerStatsDto {
|
||||
@Schema(description = "검수 작업 상태 (진행중/완료)")
|
||||
private String inspectionStatus;
|
||||
|
||||
@Schema(description = "검수 전체 대상 건수")
|
||||
@Schema(description = "검수 대상 건수 (라벨링 대상과 동일)")
|
||||
private Long inspectionTotalCount;
|
||||
|
||||
@Schema(description = "검수 완료 건수 (DONE)")
|
||||
@@ -179,10 +218,6 @@ public class WorkerStatsDto {
|
||||
@Deprecated
|
||||
@Schema(description = "[Deprecated] inspectionRemainingCount 사용 권장")
|
||||
private Long remainingInspectCount;
|
||||
|
||||
@Deprecated
|
||||
@Schema(description = "[Deprecated] labelingStatus/inspectionStatus 사용 권장")
|
||||
private String workStatus;
|
||||
}
|
||||
|
||||
@Getter
|
||||
|
||||
@@ -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.WorkerStatsDto.ProjectInfo;
|
||||
import com.kamco.cd.kamcoback.label.dto.WorkerStatsDto.WorkProgressInfo;
|
||||
import com.kamco.cd.kamcoback.label.dto.WorkerStatsDto.WorkerListResponse;
|
||||
import com.kamco.cd.kamcoback.postgres.core.LabelAllocateCoreService;
|
||||
import java.util.List;
|
||||
@@ -114,6 +116,36 @@ public class LabelAllocateService {
|
||||
return WorkerListResponse.builder().projectInfo(projectInfo).progressInfo(progressInfo).build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 작업자 통계 조회 (UUID 기반)
|
||||
*
|
||||
* @param uuid 프로젝트 UUID (선택, 미입력 시 최신 프로젝트 조회)
|
||||
* @param workerType 작업자 유형 (LABELER/INSPECTOR)
|
||||
* @param search 검색어 (이름 또는 사번)
|
||||
* @param sortType 정렬 조건
|
||||
* @return 작업자 목록 및 통계
|
||||
*/
|
||||
public WorkerListResponse getWorkerStatisticsByUuid(
|
||||
String uuid, String workerType, String search, String sortType) {
|
||||
|
||||
ProjectInfo projectInfo;
|
||||
WorkProgressInfo progressInfo;
|
||||
|
||||
if (uuid != null && !uuid.isBlank()) {
|
||||
// UUID로 프로젝트 정보 조회
|
||||
projectInfo = labelAllocateCoreService.findProjectInfoByUuid(uuid);
|
||||
// UUID로 작업 진행 현황 조회
|
||||
progressInfo = labelAllocateCoreService.findWorkProgressInfoByUuid(uuid);
|
||||
} else {
|
||||
// 최신 프로젝트 정보 조회
|
||||
projectInfo = labelAllocateCoreService.findLatestProjectInfo();
|
||||
// 최신 프로젝트 작업 진행 현황 조회
|
||||
progressInfo = labelAllocateCoreService.findWorkProgressInfo(null);
|
||||
}
|
||||
|
||||
return WorkerListResponse.builder().projectInfo(projectInfo).progressInfo(progressInfo).build();
|
||||
}
|
||||
|
||||
public InferenceDetail findInferenceDetail(String uuid) {
|
||||
return labelAllocateCoreService.findInferenceDetail(uuid);
|
||||
}
|
||||
@@ -195,4 +227,27 @@ public class LabelAllocateService {
|
||||
public MoveInfo moveAvailUserList(String userId, String uuid) {
|
||||
return labelAllocateCoreService.moveAvailUserList(userId, uuid);
|
||||
}
|
||||
|
||||
/**
|
||||
* 프로젝트 종료 여부 업데이트
|
||||
*
|
||||
* @param uuid 프로젝트 UUID (선택, 미입력 시 최신 프로젝트 대상)
|
||||
* @param closedType 종료 유형 (LABELING/INSPECTION)
|
||||
* @param closedYn 종료 여부 (Y/N)
|
||||
*/
|
||||
@Transactional
|
||||
public void updateClosedYn(String uuid, String closedType, String closedYn) {
|
||||
String targetUuid = uuid;
|
||||
|
||||
// uuid가 없으면 최신 프로젝트 uuid 조회
|
||||
if (targetUuid == null || targetUuid.isBlank()) {
|
||||
var latestProjectInfo = labelAllocateCoreService.findLatestProjectInfo();
|
||||
if (latestProjectInfo == null || latestProjectInfo.getUuid() == null) {
|
||||
throw new IllegalArgumentException("진행중인 프로젝트가 없습니다.");
|
||||
}
|
||||
targetUuid = latestProjectInfo.getUuid();
|
||||
}
|
||||
|
||||
labelAllocateCoreService.updateClosedYnByUuid(targetUuid, closedType, closedYn);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.kamco.cd.kamcoback.postgres.core;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.kamco.cd.kamcoback.common.utils.UserUtil;
|
||||
import com.kamco.cd.kamcoback.inference.dto.InferenceDetailDto;
|
||||
import com.kamco.cd.kamcoback.inference.dto.InferenceDetailDto.Dashboard;
|
||||
import com.kamco.cd.kamcoback.inference.dto.InferenceDetailDto.MapSheet;
|
||||
@@ -9,15 +9,18 @@ import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto.ResultList;
|
||||
import com.kamco.cd.kamcoback.postgres.entity.MapInkx5kEntity;
|
||||
import com.kamco.cd.kamcoback.postgres.entity.MapSheetAnalDataInferenceEntity;
|
||||
import com.kamco.cd.kamcoback.postgres.entity.MapSheetAnalDataInferenceGeomEntity;
|
||||
import com.kamco.cd.kamcoback.postgres.entity.MapSheetLearn5kEntity;
|
||||
import com.kamco.cd.kamcoback.postgres.entity.MapSheetLearnEntity;
|
||||
import com.kamco.cd.kamcoback.postgres.repository.Inference.MapSheetAnalDataInferenceRepository;
|
||||
import com.kamco.cd.kamcoback.postgres.repository.Inference.MapSheetLearn5kRepository;
|
||||
import com.kamco.cd.kamcoback.postgres.repository.Inference.MapSheetLearnRepository;
|
||||
import com.kamco.cd.kamcoback.postgres.repository.scene.MapInkx5kRepository;
|
||||
import jakarta.persistence.EntityManager;
|
||||
import jakarta.persistence.EntityNotFoundException;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.locationtech.jts.io.geojson.GeoJsonWriter;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
@@ -29,9 +32,10 @@ public class InferenceResultCoreService {
|
||||
private final MapSheetAnalDataInferenceRepository mapSheetAnalDataRepository;
|
||||
private final MapSheetLearnRepository mapSheetLearnRepository;
|
||||
private final MapInkx5kRepository mapInkx5kRepository;
|
||||
private final MapSheetLearn5kRepository mapSheetLearn5kRepository;
|
||||
|
||||
private final ObjectMapper objectMapper = new ObjectMapper();
|
||||
private final GeoJsonWriter geoJsonWriter = new GeoJsonWriter();
|
||||
private final EntityManager entityManager;
|
||||
private final UserUtil userUtil;
|
||||
|
||||
/**
|
||||
* 추론관리 목록
|
||||
@@ -55,7 +59,40 @@ public class InferenceResultCoreService {
|
||||
mapSheetLearnEntity.setM1ModelUid(req.getModel1Uid());
|
||||
mapSheetLearnEntity.setM2ModelUid(req.getModel2Uid());
|
||||
mapSheetLearnEntity.setM3ModelUid(req.getModel3Uid());
|
||||
// mapSheetLearnRepository.save()
|
||||
mapSheetLearnEntity.setCompareYyyy(req.getCompareYyyy());
|
||||
mapSheetLearnEntity.setTargetYyyy(req.getTargetYyyy());
|
||||
mapSheetLearnEntity.setMapSheetScope(req.getMapSheetScope());
|
||||
mapSheetLearnEntity.setDetectOption(req.getDetectOption());
|
||||
mapSheetLearnEntity.setCreatedUid(userUtil.getId());
|
||||
|
||||
// learn 테이블 저장
|
||||
MapSheetLearnEntity savedLearn = mapSheetLearnRepository.save(mapSheetLearnEntity);
|
||||
|
||||
final int CHUNK = 1000;
|
||||
List<MapSheetLearn5kEntity> buffer = new ArrayList<>(CHUNK);
|
||||
List<String> mapSheetNumList = req.getMapSheetNum();
|
||||
|
||||
// learn 도엽 저장
|
||||
for (String mapSheetNum : mapSheetNumList) {
|
||||
MapSheetLearn5kEntity e = new MapSheetLearn5kEntity();
|
||||
e.setLearn(savedLearn);
|
||||
e.setMapSheetNum(Long.parseLong(mapSheetNum));
|
||||
e.setCreatedUid(userUtil.getId());
|
||||
buffer.add(e);
|
||||
|
||||
if (buffer.size() == CHUNK) {
|
||||
mapSheetLearn5kRepository.saveAll(buffer);
|
||||
mapSheetLearn5kRepository.flush();
|
||||
entityManager.clear();
|
||||
buffer.clear();
|
||||
}
|
||||
}
|
||||
|
||||
if (!buffer.isEmpty()) {
|
||||
mapSheetLearn5kRepository.saveAll(buffer);
|
||||
mapSheetLearn5kRepository.flush();
|
||||
entityManager.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/****/
|
||||
|
||||
@@ -61,6 +61,10 @@ public class LabelAllocateCoreService {
|
||||
return labelAllocateRepository.findLatestProjectInfo();
|
||||
}
|
||||
|
||||
public ProjectInfo findProjectInfoByUuid(String uuid) {
|
||||
return labelAllocateRepository.findProjectInfoByUuid(uuid);
|
||||
}
|
||||
|
||||
public UUID findLastLabelWorkState() {
|
||||
return labelAllocateRepository.findLastLabelWorkState();
|
||||
}
|
||||
@@ -74,6 +78,10 @@ public class LabelAllocateCoreService {
|
||||
return labelAllocateRepository.findWorkProgressInfo(analUid);
|
||||
}
|
||||
|
||||
public WorkProgressInfo findWorkProgressInfoByUuid(String uuid) {
|
||||
return labelAllocateRepository.findWorkProgressInfoByUuid(uuid);
|
||||
}
|
||||
|
||||
public Long findDailyProcessedCount(
|
||||
String workerId, String workerType, LocalDate date, Long analUid) {
|
||||
return labelAllocateRepository.findDailyProcessedCount(workerId, workerType, date, analUid);
|
||||
@@ -133,4 +141,8 @@ public class LabelAllocateCoreService {
|
||||
String uuid, String userId, String paramUserId, Long assignCount) {
|
||||
labelAllocateRepository.assignOwnerReAllocate(uuid, userId, paramUserId, assignCount);
|
||||
}
|
||||
|
||||
public void updateClosedYnByUuid(String uuid, String closedType, String closedYn) {
|
||||
labelAllocateRepository.updateClosedYnByUuid(uuid, closedType, closedYn);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -149,4 +149,14 @@ public class MapSheetAnalInferenceEntity {
|
||||
|
||||
@Column(name = "stage")
|
||||
private Integer stage;
|
||||
|
||||
@Size(max = 1)
|
||||
@ColumnDefault("'N'")
|
||||
@Column(name = "labeling_closed_yn", length = 1)
|
||||
private String labelingClosedYn = "N";
|
||||
|
||||
@Size(max = 1)
|
||||
@ColumnDefault("'N'")
|
||||
@Column(name = "inspection_closed_yn", length = 1)
|
||||
private String inspectionClosedYn = "N";
|
||||
}
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
package com.kamco.cd.kamcoback.postgres.entity;
|
||||
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.FetchType;
|
||||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.GenerationType;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.JoinColumn;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import jakarta.persistence.SequenceGenerator;
|
||||
import jakarta.persistence.Table;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import java.time.ZonedDateTime;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.hibernate.annotations.OnDelete;
|
||||
import org.hibernate.annotations.OnDeleteAction;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Entity
|
||||
@Table(name = "tb_map_sheet_learn_5k")
|
||||
public class MapSheetLearn5kEntity {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "tb_map_sheet_learn_5k_id_gen")
|
||||
@SequenceGenerator(
|
||||
name = "tb_map_sheet_learn_5k_id_gen",
|
||||
sequenceName = "tb_map_sheet_learn_5k_seq",
|
||||
allocationSize = 1)
|
||||
@Column(name = "id", nullable = false)
|
||||
private Long id;
|
||||
|
||||
@NotNull
|
||||
@ManyToOne(fetch = FetchType.LAZY, optional = false)
|
||||
@OnDelete(action = OnDeleteAction.CASCADE)
|
||||
@JoinColumn(name = "learn_id", nullable = false, referencedColumnName = "id")
|
||||
private MapSheetLearnEntity learn;
|
||||
|
||||
@NotNull
|
||||
@Column(name = "map_sheet_num", nullable = false)
|
||||
private Long mapSheetNum;
|
||||
|
||||
@org.hibernate.annotations.CreationTimestamp
|
||||
@Column(name = "created_dttm")
|
||||
private ZonedDateTime createdDttm;
|
||||
|
||||
@Column(name = "created_uid")
|
||||
private Long createdUid;
|
||||
}
|
||||
@@ -33,7 +33,7 @@ public class MapSheetLearnEntity {
|
||||
|
||||
@ColumnDefault("gen_random_uuid()")
|
||||
@Column(name = "uuid")
|
||||
private UUID uuid;
|
||||
private UUID uuid = UUID.randomUUID();
|
||||
|
||||
@Size(max = 200)
|
||||
@NotNull
|
||||
@@ -89,7 +89,7 @@ public class MapSheetLearnEntity {
|
||||
@Column(name = "apply_dttm")
|
||||
private ZonedDateTime applyDttm;
|
||||
|
||||
@ColumnDefault("now()")
|
||||
@org.hibernate.annotations.CreationTimestamp
|
||||
@Column(name = "created_dttm")
|
||||
private ZonedDateTime createdDttm;
|
||||
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.kamco.cd.kamcoback.postgres.repository.Inference;
|
||||
|
||||
import com.kamco.cd.kamcoback.postgres.entity.MapSheetLearn5kEntity;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
public interface MapSheetLearn5kRepository
|
||||
extends JpaRepository<MapSheetLearn5kEntity, Long>, MapSheetLearn5kRepositoryCustom {}
|
||||
@@ -0,0 +1,3 @@
|
||||
package com.kamco.cd.kamcoback.postgres.repository.Inference;
|
||||
|
||||
public interface MapSheetLearn5kRepositoryCustom {}
|
||||
@@ -0,0 +1,6 @@
|
||||
package com.kamco.cd.kamcoback.postgres.repository.Inference;
|
||||
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public class MapSheetLearn5kRepositoryImpl implements MapSheetLearn5kRepositoryCustom {}
|
||||
@@ -37,6 +37,9 @@ public interface LabelAllocateRepositoryCustom {
|
||||
// 최신 프로젝트 정보 조회 (analUid 없이)
|
||||
ProjectInfo findLatestProjectInfo();
|
||||
|
||||
// UUID로 프로젝트 정보 조회
|
||||
ProjectInfo findProjectInfoByUuid(String uuid);
|
||||
|
||||
// 최신 작업 상태의 UUID 조회
|
||||
UUID findLastLabelWorkState();
|
||||
|
||||
@@ -47,6 +50,9 @@ public interface LabelAllocateRepositoryCustom {
|
||||
// 작업 진행 현황 조회
|
||||
WorkProgressInfo findWorkProgressInfo(Long analUid);
|
||||
|
||||
// UUID로 작업 진행 현황 조회
|
||||
WorkProgressInfo findWorkProgressInfoByUuid(String uuid);
|
||||
|
||||
// 작업자별 일일 처리량 조회
|
||||
Long findDailyProcessedCount(String workerId, String workerType, LocalDate date, Long analUid);
|
||||
|
||||
@@ -77,4 +83,7 @@ public interface LabelAllocateRepositoryCustom {
|
||||
void insertLabelerUser(Long analUid, String userId, int demand);
|
||||
|
||||
void assignOwnerReAllocate(String uuid, String userId, String paramUserId, Long assignCount);
|
||||
|
||||
// 프로젝트 종료 여부 업데이트 (uuid 기반)
|
||||
void updateClosedYnByUuid(String uuid, String closedType, String closedYn);
|
||||
}
|
||||
|
||||
@@ -335,10 +335,50 @@ public class LabelAllocateRepositoryImpl implements LabelAllocateRepositoryCusto
|
||||
|
||||
@Override
|
||||
public WorkProgressInfo findWorkProgressInfo(Long analUid) {
|
||||
BooleanExpression analUidCondition =
|
||||
analUid != null ? labelingAssignmentEntity.analUid.eq(analUid) : null;
|
||||
// analUid가 null이면 최신 프로젝트의 analUid 조회
|
||||
Long effectiveAnalUid = analUid;
|
||||
if (effectiveAnalUid == null) {
|
||||
UUID latestUuid = findLastLabelWorkState();
|
||||
if (latestUuid != null) {
|
||||
effectiveAnalUid =
|
||||
queryFactory
|
||||
.select(mapSheetAnalInferenceEntity.id)
|
||||
.from(mapSheetAnalInferenceEntity)
|
||||
.where(mapSheetAnalInferenceEntity.uuid.eq(latestUuid))
|
||||
.fetchOne();
|
||||
}
|
||||
}
|
||||
|
||||
// 전체 배정 건수
|
||||
BooleanExpression analUidCondition =
|
||||
effectiveAnalUid != null ? labelingAssignmentEntity.analUid.eq(effectiveAnalUid) : null;
|
||||
|
||||
// analUid로 분석 정보(compareYyyy, targetYyyy, stage) 조회
|
||||
MapSheetAnalInferenceEntity analEntity = null;
|
||||
if (effectiveAnalUid != null) {
|
||||
analEntity =
|
||||
queryFactory
|
||||
.selectFrom(mapSheetAnalInferenceEntity)
|
||||
.where(mapSheetAnalInferenceEntity.id.eq(effectiveAnalUid))
|
||||
.fetchOne();
|
||||
}
|
||||
|
||||
// 라벨링 대상 건수: tb_map_sheet_anal_data_inference_geom에서 pnu > 0 AND pass_yn = false(부적합)인 건수
|
||||
Long labelingTargetCount = 0L;
|
||||
if (analEntity != null) {
|
||||
labelingTargetCount =
|
||||
queryFactory
|
||||
.select(mapSheetAnalDataInferenceGeomEntity.geoUid.count())
|
||||
.from(mapSheetAnalDataInferenceGeomEntity)
|
||||
.where(
|
||||
mapSheetAnalDataInferenceGeomEntity.compareYyyy.eq(analEntity.getCompareYyyy()),
|
||||
mapSheetAnalDataInferenceGeomEntity.targetYyyy.eq(analEntity.getTargetYyyy()),
|
||||
mapSheetAnalDataInferenceGeomEntity.stage.eq(analEntity.getStage()),
|
||||
mapSheetAnalDataInferenceGeomEntity.pnu.gt(0L),
|
||||
mapSheetAnalDataInferenceGeomEntity.passYn.isFalse())
|
||||
.fetchOne();
|
||||
}
|
||||
|
||||
// 전체 배정 건수 (tb_labeling_assignment 기준)
|
||||
Long totalAssigned =
|
||||
queryFactory
|
||||
.select(labelingAssignmentEntity.count())
|
||||
@@ -390,47 +430,217 @@ public class LabelAllocateRepositoryImpl implements LabelAllocateRepositoryCusto
|
||||
.where(analUidCondition, labelingAssignmentEntity.inspectorUid.isNotNull())
|
||||
.fetchOne();
|
||||
|
||||
// 남은 작업 건수 계산
|
||||
long total = totalAssigned != null ? totalAssigned : 0L;
|
||||
// 라벨링 대상 건수 (pass_yn = false인 부적합 데이터 기준)
|
||||
long labelingTotal = labelingTargetCount != null ? labelingTargetCount : 0L;
|
||||
long assignedTotal = 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;
|
||||
// 라벨링 남은 건수: 라벨링 대상 건수 - 완료 - 스킵
|
||||
long labelingRemaining = labelingTotal - labelCompleted - skipped;
|
||||
if (labelingRemaining < 0) labelingRemaining = 0;
|
||||
|
||||
// 진행률 계산
|
||||
double labelingRate = total > 0 ? (double) labelCompleted / total * 100 : 0.0;
|
||||
double inspectionRate = total > 0 ? (double) inspectCompleted / total * 100 : 0.0;
|
||||
// 검수 대상 건수: 라벨링 대상 건수와 동일 (기획서 기준)
|
||||
long inspectionTotal = labelingTotal;
|
||||
// 검수 남은 건수: 검수 대상 건수 - 검수완료(DONE) - 스킵
|
||||
long inspectionRemaining = inspectionTotal - inspectCompleted - skipped;
|
||||
if (inspectionRemaining < 0) inspectionRemaining = 0;
|
||||
|
||||
// 상태 판단
|
||||
String labelingStatus = labelingRemaining > 0 ? "진행중" : "완료";
|
||||
String inspectionStatus = inspectionRemaining > 0 ? "진행중" : "완료";
|
||||
// 진행률 계산 (라벨링 대상 건수 기준)
|
||||
double labelingRate = labelingTotal > 0 ? (double) labelCompleted / labelingTotal * 100 : 0.0;
|
||||
double inspectionRate =
|
||||
inspectionTotal > 0 ? (double) inspectCompleted / inspectionTotal * 100 : 0.0;
|
||||
|
||||
// 상태 판단 (각각의 closedYn이 "Y"이면 "종료", 아니면 진행중/완료)
|
||||
String labelingStatus;
|
||||
String inspectionStatus;
|
||||
|
||||
// 라벨링 상태 판단
|
||||
if (analEntity != null && "Y".equals(analEntity.getLabelingClosedYn())) {
|
||||
labelingStatus = "종료";
|
||||
} else {
|
||||
labelingStatus = labelingRemaining > 0 ? "진행중" : "완료";
|
||||
}
|
||||
|
||||
// 검수 상태 판단
|
||||
if (analEntity != null && "Y".equals(analEntity.getInspectionClosedYn())) {
|
||||
inspectionStatus = "종료";
|
||||
} else {
|
||||
inspectionStatus = inspectionRemaining > 0 ? "진행중" : "완료";
|
||||
}
|
||||
|
||||
return WorkProgressInfo.builder()
|
||||
// 라벨링
|
||||
// 라벨링 (pass_yn = false인 부적합 데이터 기준)
|
||||
.labelingProgressRate(labelingRate)
|
||||
.labelingStatus(labelingStatus)
|
||||
.labelingTotalCount(total)
|
||||
.labelingTotalCount(labelingTotal)
|
||||
.labelingCompletedCount(labelCompleted)
|
||||
.labelingSkipCount(skipped)
|
||||
.labelingRemainingCount(labelingRemaining)
|
||||
.labelerCount(labelerCount != null ? labelerCount : 0L)
|
||||
// 검수
|
||||
// 검수 (라벨링 완료 건수 기준)
|
||||
.inspectionProgressRate(inspectionRate)
|
||||
.inspectionStatus(inspectionStatus)
|
||||
.inspectionTotalCount(total)
|
||||
.inspectionTotalCount(inspectionTotal)
|
||||
.inspectionCompletedCount(inspectCompleted)
|
||||
.inspectionSkipCount(skipped)
|
||||
.inspectionRemainingCount(inspectionRemaining)
|
||||
.inspectorCount(inspectorCount != null ? inspectorCount : 0L)
|
||||
// 레거시 호환 필드 (Deprecated)
|
||||
.progressRate(labelingRate)
|
||||
.totalAssignedCount(total)
|
||||
.totalAssignedCount(labelingTotal)
|
||||
.completedCount(labelCompleted)
|
||||
.remainingLabelCount(labelingRemaining)
|
||||
.remainingInspectCount(inspectionRemaining)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public WorkProgressInfo findWorkProgressInfoByUuid(String uuid) {
|
||||
if (uuid == null || uuid.isBlank()) {
|
||||
return findWorkProgressInfo(null);
|
||||
}
|
||||
|
||||
UUID targetUuid = UUID.fromString(uuid);
|
||||
|
||||
// UUID로 analUid 조회
|
||||
Long effectiveAnalUid =
|
||||
queryFactory
|
||||
.select(mapSheetAnalInferenceEntity.id)
|
||||
.from(mapSheetAnalInferenceEntity)
|
||||
.where(mapSheetAnalInferenceEntity.uuid.eq(targetUuid))
|
||||
.fetchOne();
|
||||
|
||||
if (effectiveAnalUid == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
BooleanExpression analUidCondition = labelingAssignmentEntity.analUid.eq(effectiveAnalUid);
|
||||
|
||||
// analUid로 분석 정보(compareYyyy, targetYyyy, stage) 조회
|
||||
MapSheetAnalInferenceEntity analEntity =
|
||||
queryFactory
|
||||
.selectFrom(mapSheetAnalInferenceEntity)
|
||||
.where(mapSheetAnalInferenceEntity.id.eq(effectiveAnalUid))
|
||||
.fetchOne();
|
||||
|
||||
// 라벨링 대상 건수: tb_map_sheet_anal_data_inference_geom에서 pnu > 0 AND pass_yn = false(부적합)인 건수
|
||||
Long labelingTargetCount = 0L;
|
||||
if (analEntity != null) {
|
||||
labelingTargetCount =
|
||||
queryFactory
|
||||
.select(mapSheetAnalDataInferenceGeomEntity.geoUid.count())
|
||||
.from(mapSheetAnalDataInferenceGeomEntity)
|
||||
.where(
|
||||
mapSheetAnalDataInferenceGeomEntity.compareYyyy.eq(analEntity.getCompareYyyy()),
|
||||
mapSheetAnalDataInferenceGeomEntity.targetYyyy.eq(analEntity.getTargetYyyy()),
|
||||
mapSheetAnalDataInferenceGeomEntity.stage.eq(analEntity.getStage()),
|
||||
mapSheetAnalDataInferenceGeomEntity.pnu.gt(0L),
|
||||
mapSheetAnalDataInferenceGeomEntity.passYn.isFalse())
|
||||
.fetchOne();
|
||||
}
|
||||
|
||||
// 전체 배정 건수 (tb_labeling_assignment 기준)
|
||||
Long totalAssigned =
|
||||
queryFactory
|
||||
.select(labelingAssignmentEntity.count())
|
||||
.from(labelingAssignmentEntity)
|
||||
.where(analUidCondition)
|
||||
.fetchOne();
|
||||
|
||||
// === 라벨링 통계 ===
|
||||
Long labelingCompleted =
|
||||
queryFactory
|
||||
.select(labelingAssignmentEntity.count())
|
||||
.from(labelingAssignmentEntity)
|
||||
.where(
|
||||
analUidCondition,
|
||||
labelingAssignmentEntity.workState.in("LABEL_FIN", "TEST_ING", "DONE"))
|
||||
.fetchOne();
|
||||
|
||||
Long skipCount =
|
||||
queryFactory
|
||||
.select(labelingAssignmentEntity.count())
|
||||
.from(labelingAssignmentEntity)
|
||||
.where(analUidCondition, labelingAssignmentEntity.workState.eq("SKIP"))
|
||||
.fetchOne();
|
||||
|
||||
Long labelerCount =
|
||||
queryFactory
|
||||
.select(labelingAssignmentEntity.workerUid.countDistinct())
|
||||
.from(labelingAssignmentEntity)
|
||||
.where(analUidCondition, labelingAssignmentEntity.workerUid.isNotNull())
|
||||
.fetchOne();
|
||||
|
||||
// === 검수 통계 ===
|
||||
Long inspectionCompleted =
|
||||
queryFactory
|
||||
.select(labelingAssignmentEntity.count())
|
||||
.from(labelingAssignmentEntity)
|
||||
.where(analUidCondition, labelingAssignmentEntity.workState.eq("DONE"))
|
||||
.fetchOne();
|
||||
|
||||
Long inspectorCount =
|
||||
queryFactory
|
||||
.select(labelingAssignmentEntity.inspectorUid.countDistinct())
|
||||
.from(labelingAssignmentEntity)
|
||||
.where(analUidCondition, labelingAssignmentEntity.inspectorUid.isNotNull())
|
||||
.fetchOne();
|
||||
|
||||
// 계산
|
||||
long labelingTotal = labelingTargetCount != null ? labelingTargetCount : 0L;
|
||||
long labelCompleted = labelingCompleted != null ? labelingCompleted : 0L;
|
||||
long inspectCompleted = inspectionCompleted != null ? inspectionCompleted : 0L;
|
||||
long skipped = skipCount != null ? skipCount : 0L;
|
||||
|
||||
long labelingRemaining = labelingTotal - labelCompleted - skipped;
|
||||
if (labelingRemaining < 0) labelingRemaining = 0;
|
||||
|
||||
long inspectionTotal = labelingTotal;
|
||||
long inspectionRemaining = inspectionTotal - inspectCompleted - skipped;
|
||||
if (inspectionRemaining < 0) inspectionRemaining = 0;
|
||||
|
||||
double labelingRate = labelingTotal > 0 ? (double) labelCompleted / labelingTotal * 100 : 0.0;
|
||||
double inspectionRate =
|
||||
inspectionTotal > 0 ? (double) inspectCompleted / inspectionTotal * 100 : 0.0;
|
||||
|
||||
// 상태 판단
|
||||
String labelingStatus;
|
||||
String inspectionStatus;
|
||||
|
||||
if (analEntity != null && "Y".equals(analEntity.getLabelingClosedYn())) {
|
||||
labelingStatus = "종료";
|
||||
} else {
|
||||
labelingStatus = labelingRemaining > 0 ? "진행중" : "완료";
|
||||
}
|
||||
|
||||
if (analEntity != null && "Y".equals(analEntity.getInspectionClosedYn())) {
|
||||
inspectionStatus = "종료";
|
||||
} else {
|
||||
inspectionStatus = inspectionRemaining > 0 ? "진행중" : "완료";
|
||||
}
|
||||
|
||||
return WorkProgressInfo.builder()
|
||||
.labelingProgressRate(labelingRate)
|
||||
.labelingStatus(labelingStatus)
|
||||
.labelingTotalCount(labelingTotal)
|
||||
.labelingCompletedCount(labelCompleted)
|
||||
.labelingSkipCount(skipped)
|
||||
.labelingRemainingCount(labelingRemaining)
|
||||
.labelerCount(labelerCount != null ? labelerCount : 0L)
|
||||
.inspectionProgressRate(inspectionRate)
|
||||
.inspectionStatus(inspectionStatus)
|
||||
.inspectionTotalCount(inspectionTotal)
|
||||
.inspectionCompletedCount(inspectCompleted)
|
||||
.inspectionSkipCount(skipped)
|
||||
.inspectionRemainingCount(inspectionRemaining)
|
||||
.inspectorCount(inspectorCount != null ? inspectorCount : 0L)
|
||||
.progressRate(labelingRate)
|
||||
.totalAssignedCount(labelingTotal)
|
||||
.completedCount(labelCompleted)
|
||||
.remainingLabelCount(labelingRemaining)
|
||||
.remainingInspectCount(inspectionRemaining)
|
||||
.workStatus(labelingStatus)
|
||||
.build();
|
||||
}
|
||||
|
||||
@@ -677,7 +887,9 @@ public class LabelAllocateRepositoryImpl implements LabelAllocateRepositoryCusto
|
||||
mapSheetAnalInferenceEntity.stage,
|
||||
mapSheetAnalInferenceEntity.gukyuinApplyDttm,
|
||||
mapSheetAnalInferenceEntity.createdDttm,
|
||||
mapSheetAnalInferenceEntity.uuid)
|
||||
mapSheetAnalInferenceEntity.uuid,
|
||||
mapSheetAnalInferenceEntity.labelingClosedYn,
|
||||
mapSheetAnalInferenceEntity.inspectionClosedYn)
|
||||
.from(mapSheetAnalInferenceEntity)
|
||||
.where(mapSheetAnalInferenceEntity.id.eq(analUid))
|
||||
.fetchOne();
|
||||
@@ -692,6 +904,8 @@ public class LabelAllocateRepositoryImpl implements LabelAllocateRepositoryCusto
|
||||
ZonedDateTime gukyuinApplyDttm = result.get(mapSheetAnalInferenceEntity.gukyuinApplyDttm);
|
||||
ZonedDateTime createdDttm = result.get(mapSheetAnalInferenceEntity.createdDttm);
|
||||
UUID uuid = result.get(mapSheetAnalInferenceEntity.uuid);
|
||||
String labelingClosedYn = result.get(mapSheetAnalInferenceEntity.labelingClosedYn);
|
||||
String inspectionClosedYn = result.get(mapSheetAnalInferenceEntity.inspectionClosedYn);
|
||||
|
||||
// 변화탐지년도 생성
|
||||
String detectionYear =
|
||||
@@ -706,6 +920,8 @@ public class LabelAllocateRepositoryImpl implements LabelAllocateRepositoryCusto
|
||||
.gukyuinApplyDttm(gukyuinApplyDttm)
|
||||
.startDttm(createdDttm)
|
||||
.uuid(uuid != null ? uuid.toString() : null)
|
||||
.labelingClosedYn(labelingClosedYn)
|
||||
.inspectionClosedYn(inspectionClosedYn)
|
||||
.build();
|
||||
}
|
||||
|
||||
@@ -727,7 +943,9 @@ public class LabelAllocateRepositoryImpl implements LabelAllocateRepositoryCusto
|
||||
mapSheetAnalInferenceEntity.stage,
|
||||
mapSheetAnalInferenceEntity.gukyuinApplyDttm,
|
||||
mapSheetAnalInferenceEntity.createdDttm,
|
||||
mapSheetAnalInferenceEntity.uuid)
|
||||
mapSheetAnalInferenceEntity.uuid,
|
||||
mapSheetAnalInferenceEntity.labelingClosedYn,
|
||||
mapSheetAnalInferenceEntity.inspectionClosedYn)
|
||||
.from(mapSheetAnalInferenceEntity)
|
||||
.where(mapSheetAnalInferenceEntity.uuid.eq(uuid))
|
||||
.fetchOne();
|
||||
@@ -741,6 +959,8 @@ public class LabelAllocateRepositoryImpl implements LabelAllocateRepositoryCusto
|
||||
Integer stage = result.get(mapSheetAnalInferenceEntity.stage);
|
||||
ZonedDateTime gukyuinApplyDttm = result.get(mapSheetAnalInferenceEntity.gukyuinApplyDttm);
|
||||
ZonedDateTime createdDttm = result.get(mapSheetAnalInferenceEntity.createdDttm);
|
||||
String labelingClosedYn = result.get(mapSheetAnalInferenceEntity.labelingClosedYn);
|
||||
String inspectionClosedYn = result.get(mapSheetAnalInferenceEntity.inspectionClosedYn);
|
||||
|
||||
// 변화탐지년도 생성
|
||||
String detectionYear =
|
||||
@@ -755,6 +975,58 @@ public class LabelAllocateRepositoryImpl implements LabelAllocateRepositoryCusto
|
||||
.gukyuinApplyDttm(gukyuinApplyDttm)
|
||||
.startDttm(createdDttm)
|
||||
.uuid(uuid.toString())
|
||||
.labelingClosedYn(labelingClosedYn)
|
||||
.inspectionClosedYn(inspectionClosedYn)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProjectInfo findProjectInfoByUuid(String uuid) {
|
||||
if (uuid == null || uuid.isBlank()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
UUID targetUuid = UUID.fromString(uuid);
|
||||
|
||||
var result =
|
||||
queryFactory
|
||||
.select(
|
||||
mapSheetAnalInferenceEntity.compareYyyy,
|
||||
mapSheetAnalInferenceEntity.targetYyyy,
|
||||
mapSheetAnalInferenceEntity.stage,
|
||||
mapSheetAnalInferenceEntity.gukyuinApplyDttm,
|
||||
mapSheetAnalInferenceEntity.createdDttm,
|
||||
mapSheetAnalInferenceEntity.uuid,
|
||||
mapSheetAnalInferenceEntity.labelingClosedYn,
|
||||
mapSheetAnalInferenceEntity.inspectionClosedYn)
|
||||
.from(mapSheetAnalInferenceEntity)
|
||||
.where(mapSheetAnalInferenceEntity.uuid.eq(targetUuid))
|
||||
.fetchOne();
|
||||
|
||||
if (result == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Integer compareYyyy = result.get(mapSheetAnalInferenceEntity.compareYyyy);
|
||||
Integer targetYyyy = result.get(mapSheetAnalInferenceEntity.targetYyyy);
|
||||
Integer stage = result.get(mapSheetAnalInferenceEntity.stage);
|
||||
ZonedDateTime gukyuinApplyDttm = result.get(mapSheetAnalInferenceEntity.gukyuinApplyDttm);
|
||||
ZonedDateTime createdDttm = result.get(mapSheetAnalInferenceEntity.createdDttm);
|
||||
String labelingClosedYn = result.get(mapSheetAnalInferenceEntity.labelingClosedYn);
|
||||
String inspectionClosedYn = result.get(mapSheetAnalInferenceEntity.inspectionClosedYn);
|
||||
|
||||
String detectionYear =
|
||||
(compareYyyy != null && targetYyyy != null) ? compareYyyy + "-" + targetYyyy : null;
|
||||
String round = stage != null ? String.valueOf(stage) : null;
|
||||
|
||||
return ProjectInfo.builder()
|
||||
.detectionYear(detectionYear)
|
||||
.stage(round)
|
||||
.gukyuinApplyDttm(gukyuinApplyDttm)
|
||||
.startDttm(createdDttm)
|
||||
.uuid(uuid)
|
||||
.labelingClosedYn(labelingClosedYn)
|
||||
.inspectionClosedYn(inspectionClosedYn)
|
||||
.build();
|
||||
}
|
||||
|
||||
@@ -1160,4 +1432,23 @@ public class LabelAllocateRepositoryImpl implements LabelAllocateRepositoryCusto
|
||||
labelingLabelerEntity.workerUid.eq(paramUserId))
|
||||
.execute();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateClosedYnByUuid(String uuid, String closedType, String closedYn) {
|
||||
var updateQuery = queryFactory.update(mapSheetAnalInferenceEntity);
|
||||
|
||||
if ("LABELING".equals(closedType)) {
|
||||
updateQuery.set(mapSheetAnalInferenceEntity.labelingClosedYn, closedYn);
|
||||
} else if ("INSPECTION".equals(closedType)) {
|
||||
updateQuery.set(mapSheetAnalInferenceEntity.inspectionClosedYn, closedYn);
|
||||
}
|
||||
|
||||
updateQuery
|
||||
.set(mapSheetAnalInferenceEntity.updatedDttm, ZonedDateTime.now())
|
||||
.where(mapSheetAnalInferenceEntity.uuid.eq(UUID.fromString(uuid)))
|
||||
.execute();
|
||||
|
||||
em.flush();
|
||||
em.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -265,32 +265,29 @@ public class LabelWorkRepositoryImpl implements LabelWorkRepositoryCustom {
|
||||
|
||||
whereSubBuilder.and(labelingAssignmentEntity.workerUid.eq(memberEntity.userId));
|
||||
|
||||
// 공통 조건 추출
|
||||
BooleanExpression doneStateCondition =
|
||||
labelingAssignmentEntity.workState.eq(LabelState.DONE.name());
|
||||
|
||||
NumberExpression<Long> assignedCnt = labelingAssignmentEntity.workerUid.count();
|
||||
NumberExpression<Long> doneCnt =
|
||||
this.caseSumExpression(labelingAssignmentEntity.workState.eq(LabelState.DONE.name()));
|
||||
NumberExpression<Long> doneCnt = this.caseSumExpression(doneStateCondition);
|
||||
NumberExpression<Long> skipCnt =
|
||||
this.caseSumExpression(labelingAssignmentEntity.workState.eq(LabelState.SKIP.name()));
|
||||
|
||||
NumberExpression<Long> day3AgoDoneCnt =
|
||||
this.caseSumExpression(
|
||||
labelingAssignmentEntity
|
||||
.workState
|
||||
.eq(LabelState.DONE.name())
|
||||
.and(this.fromDateEqExpression(labelingAssignmentEntity.modifiedDate, -3)));
|
||||
doneStateCondition.and(
|
||||
this.fromDateEqExpression(labelingAssignmentEntity.modifiedDate, -3)));
|
||||
|
||||
NumberExpression<Long> day2AgoDoneCnt =
|
||||
this.caseSumExpression(
|
||||
labelingAssignmentEntity
|
||||
.workState
|
||||
.eq(LabelState.DONE.name())
|
||||
.and(this.fromDateEqExpression(labelingAssignmentEntity.modifiedDate, -2)));
|
||||
doneStateCondition.and(
|
||||
this.fromDateEqExpression(labelingAssignmentEntity.modifiedDate, -2)));
|
||||
|
||||
NumberExpression<Long> day1AgoDoneCnt =
|
||||
this.caseSumExpression(
|
||||
labelingAssignmentEntity
|
||||
.workState
|
||||
.eq(LabelState.DONE.name())
|
||||
.and(this.fromDateEqExpression(labelingAssignmentEntity.modifiedDate, -1)));
|
||||
doneStateCondition.and(
|
||||
this.fromDateEqExpression(labelingAssignmentEntity.modifiedDate, -1)));
|
||||
|
||||
NumberExpression<Long> remainingCnt = assignedCnt.subtract(doneCnt);
|
||||
|
||||
|
||||
@@ -11,8 +11,11 @@ spring:
|
||||
hibernate:
|
||||
default_batch_fetch_size: 100 # ✅ 성능 - N+1 쿼리 방지
|
||||
order_updates: true # ✅ 성능 - 업데이트 순서 정렬로 데드락 방지
|
||||
order_inserts: true
|
||||
use_sql_comments: true # ⚠️ 선택 - SQL에 주석 추가 (디버깅용)
|
||||
format_sql: true # ⚠️ 선택 - SQL 포맷팅 (가독성)
|
||||
jdbc:
|
||||
batch_size: 1000 # ✅ 추가 (JDBC batch)
|
||||
|
||||
datasource:
|
||||
url: jdbc:postgresql://192.168.2.127:15432/kamco_cds
|
||||
|
||||
@@ -4,14 +4,18 @@ spring:
|
||||
on-profile: prod
|
||||
|
||||
jpa:
|
||||
show-sql: false
|
||||
show-sql: true
|
||||
hibernate:
|
||||
ddl-auto: validate
|
||||
properties:
|
||||
hibernate:
|
||||
default_batch_fetch_size: 100 # ✅ 성능 - N+1 쿼리 방지
|
||||
order_updates: true # ✅ 성능 - 업데이트 순서 정렬로 데드락 방지
|
||||
order_inserts: true
|
||||
use_sql_comments: true # ⚠️ 선택 - SQL에 주석 추가 (디버깅용)
|
||||
format_sql: true # ⚠️ 선택 - SQL 포맷팅 (가독성)
|
||||
jdbc:
|
||||
batch_size: 1000 # ✅ 추가 (JDBC batch)
|
||||
|
||||
datasource:
|
||||
url: jdbc:postgresql://10.100.0.10:25432/temp
|
||||
|
||||
Reference in New Issue
Block a user