라벨링 추가할당 API 추가, 라벨링툴 목록 도엽순으로 소팅 #82
@@ -28,6 +28,7 @@ import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
@@ -458,4 +459,43 @@ public class LabelAllocateApiController {
|
||||
UUID uuid) {
|
||||
return ApiResponseDto.ok(labelAllocateService.isDownloadable(uuid));
|
||||
}
|
||||
|
||||
@Operation(
|
||||
summary = "라벨링작업 관리 > 추가 작업 배정(실태조사 추가되면)",
|
||||
description = "라벨링작업 관리 > 추가 작업 배정(실태조사 추가되면)")
|
||||
@ApiResponses(
|
||||
value = {
|
||||
@ApiResponse(
|
||||
responseCode = "201",
|
||||
description = "등록 성공",
|
||||
content =
|
||||
@Content(
|
||||
mediaType = "application/json",
|
||||
schema = @Schema(implementation = Long.class))),
|
||||
@ApiResponse(responseCode = "400", description = "잘못된 요청 데이터", content = @Content),
|
||||
@ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content),
|
||||
@ApiResponse(responseCode = "500", description = "서버 오류", content = @Content)
|
||||
})
|
||||
@PostMapping("/allocate-add-stblt")
|
||||
public ApiResponseDto<ApiResponseDto.ResponseObj> labelAllocateAddStblt(
|
||||
@RequestBody @Valid LabelAllocateDto.AllocateAddStbltDto dto) {
|
||||
|
||||
return ApiResponseDto.okObject(
|
||||
labelAllocateService.allocateAddStbltYn(
|
||||
dto.getTotalCnt(), dto.getUuid(), dto.getLabelers(), dto.getBaseDate()));
|
||||
}
|
||||
|
||||
@Operation(summary = "라벨링 추가 할당 가능한 건수", description = "라벨링 추가 할당 가능한 건수 API")
|
||||
@ApiResponses(
|
||||
value = {
|
||||
@ApiResponse(responseCode = "200", description = "조회 성공"),
|
||||
@ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음"),
|
||||
@ApiResponse(responseCode = "500", description = "서버 오류")
|
||||
})
|
||||
@GetMapping("/allocate-add-cnt")
|
||||
public ApiResponseDto<Long> allocateAddCnt(
|
||||
@RequestParam UUID uuid, @RequestParam LocalDate baseDate) {
|
||||
|
||||
return ApiResponseDto.ok(labelAllocateService.findAllocateAddCnt(uuid, baseDate));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.kamco.cd.kamcoback.label.dto;
|
||||
import com.kamco.cd.kamcoback.common.utils.enums.CodeExpose;
|
||||
import com.kamco.cd.kamcoback.common.utils.enums.EnumType;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import java.time.LocalDate;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
@@ -365,9 +366,35 @@ public class LabelAllocateDto {
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public static class InferenceLearnDto {
|
||||
|
||||
private UUID analUuid;
|
||||
private String learnUid;
|
||||
private String analState;
|
||||
private Long analId;
|
||||
}
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@AllArgsConstructor
|
||||
public static class AllocateAddStbltDto {
|
||||
|
||||
@Schema(description = "총 잔여 건수", example = "179")
|
||||
private Integer totalCnt;
|
||||
|
||||
@Schema(
|
||||
description = "추가할당할 라벨러",
|
||||
example =
|
||||
"""
|
||||
[
|
||||
"123454", "654321", "222233", "777222"
|
||||
]
|
||||
""")
|
||||
private List<String> labelers;
|
||||
|
||||
@Schema(description = "회차 마스터 key", example = "c0e77cc7-8c28-46ba-9ca4-11e90246ab44")
|
||||
private UUID uuid;
|
||||
|
||||
@Schema(description = "기준일자", example = "2026-02-20")
|
||||
private LocalDate baseDate;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import com.kamco.cd.kamcoback.log.dto.AuditLogDto;
|
||||
import com.kamco.cd.kamcoback.log.dto.AuditLogDto.DownloadReq;
|
||||
import com.kamco.cd.kamcoback.postgres.core.AuditLogCoreService;
|
||||
import com.kamco.cd.kamcoback.postgres.core.LabelAllocateCoreService;
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
@@ -302,4 +303,52 @@ public class LabelAllocateService {
|
||||
public boolean isDownloadable(UUID uuid) {
|
||||
return labelAllocateCoreService.isDownloadable(uuid);
|
||||
}
|
||||
|
||||
/**
|
||||
* 실태조사가 값 들어온 기간만큼 할당하는 로직 (최초 할당 이후 작업)
|
||||
*
|
||||
* @param uuid
|
||||
* @param targetUsers
|
||||
* @return
|
||||
*/
|
||||
@Transactional
|
||||
public ApiResponseDto.ResponseObj allocateAddStbltYn(
|
||||
Integer totalCnt, UUID uuid, List<String> targetUsers, LocalDate baseDate) {
|
||||
|
||||
int userCount = targetUsers.size();
|
||||
if (userCount == 0) {
|
||||
return new ApiResponseDto.ResponseObj(ApiResponseCode.BAD_REQUEST, "추가 할당할 라벨러를 선택해주세요.");
|
||||
}
|
||||
|
||||
int base = totalCnt / userCount;
|
||||
int remainder = totalCnt % userCount;
|
||||
Long lastId = null;
|
||||
List<AllocateInfoDto> allIds =
|
||||
labelAllocateCoreService.fetchNextIdsAddStbltYn(
|
||||
uuid, baseDate, lastId, totalCnt.longValue());
|
||||
|
||||
// MapSheetAnalInferenceEntity analUid 가져오기
|
||||
Long analUid = labelAllocateCoreService.findMapSheetAnalInferenceUid(uuid);
|
||||
|
||||
int index = 0;
|
||||
for (int i = 0; i < userCount; i++) {
|
||||
int assignCount = base;
|
||||
// 마지막 사람에게 나머지 몰아주기
|
||||
if (i == userCount - 1) {
|
||||
assignCount += remainder;
|
||||
}
|
||||
|
||||
int end = index + assignCount;
|
||||
List<AllocateInfoDto> sub = allIds.subList(index, end);
|
||||
|
||||
labelAllocateCoreService.assignOwner(sub, targetUsers.get(i), analUid);
|
||||
index = end;
|
||||
}
|
||||
|
||||
return new ApiResponseDto.ResponseObj(ApiResponseCode.OK, "추가 할당이 완료되었습니다.");
|
||||
}
|
||||
|
||||
public Long findAllocateAddCnt(UUID uuid, LocalDate baseDate) {
|
||||
return labelAllocateCoreService.findAllocateAddCnt(uuid, baseDate);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -257,7 +257,9 @@ public class LabelAllocateCoreService {
|
||||
|
||||
// 파일이 있는지만 확인
|
||||
Path path = Paths.get(responsePath).resolve(dto.getLearnUid() + ".zip");
|
||||
if (!Files.isRegularFile(path)) return false; // exists 포함
|
||||
if (!Files.isRegularFile(path)) {
|
||||
return false; // exists 포함
|
||||
}
|
||||
|
||||
String state = dto.getAnalState();
|
||||
boolean isLabelingIng =
|
||||
@@ -265,7 +267,9 @@ public class LabelAllocateCoreService {
|
||||
|
||||
if (isLabelingIng) {
|
||||
Long analId = dto.getAnalId();
|
||||
if (analId == null) return false;
|
||||
if (analId == null) {
|
||||
return false;
|
||||
}
|
||||
return batchStepHistoryRepository.isDownloadable(analId);
|
||||
}
|
||||
|
||||
@@ -277,4 +281,13 @@ public class LabelAllocateCoreService {
|
||||
.findLearnUid(uuid)
|
||||
.orElseThrow(() -> new CustomApiException("NOT_FOUND_DATA", HttpStatus.NOT_FOUND));
|
||||
}
|
||||
|
||||
public List<AllocateInfoDto> fetchNextIdsAddStbltYn(
|
||||
UUID uuid, LocalDate baseDate, Long lastId, Long totalCnt) {
|
||||
return labelAllocateRepository.fetchNextIdsAddStbltYn(uuid, baseDate, lastId, totalCnt);
|
||||
}
|
||||
|
||||
public Long findAllocateAddCnt(UUID uuid, LocalDate baseDate) {
|
||||
return labelAllocateRepository.findAllocateAddCnt(uuid, baseDate);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,4 +110,9 @@ public interface LabelAllocateRepositoryCustom {
|
||||
InferenceLearnDto findLabelingIngProcessId(UUID uuid);
|
||||
|
||||
Optional<String> findLearnUid(UUID uuid);
|
||||
|
||||
List<AllocateInfoDto> fetchNextIdsAddStbltYn(
|
||||
UUID uuid, LocalDate baseDate, Long lastId, Long totalCnt);
|
||||
|
||||
Long findAllocateAddCnt(UUID uuid, LocalDate baseDate);
|
||||
}
|
||||
|
||||
@@ -1856,4 +1856,56 @@ public class LabelAllocateRepositoryImpl implements LabelAllocateRepositoryCusto
|
||||
.where(mapSheetAnalInferenceEntity.uuid.eq(uuid))
|
||||
.fetchOne());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AllocateInfoDto> fetchNextIdsAddStbltYn(
|
||||
UUID uuid, LocalDate baseDate, Long lastId, Long totalCnt) {
|
||||
ZoneId zone = ZoneId.of("Asia/Seoul"); // 기준 타임존 명확히
|
||||
ZonedDateTime nextDayStart = baseDate.plusDays(1).atStartOfDay(zone);
|
||||
|
||||
return queryFactory
|
||||
.select(
|
||||
Projections.constructor(
|
||||
AllocateInfoDto.class,
|
||||
mapSheetAnalDataInferenceGeomEntity.geoUid,
|
||||
mapSheetAnalDataInferenceGeomEntity.mapSheetNum,
|
||||
mapSheetAnalDataInferenceGeomEntity.pnu))
|
||||
.from(mapSheetAnalInferenceEntity)
|
||||
.innerJoin(mapSheetAnalDataInferenceEntity)
|
||||
.on(mapSheetAnalInferenceEntity.id.eq(mapSheetAnalDataInferenceEntity.analUid))
|
||||
.innerJoin(mapSheetAnalDataInferenceGeomEntity)
|
||||
.on(
|
||||
mapSheetAnalDataInferenceEntity.id.eq(mapSheetAnalDataInferenceGeomEntity.dataUid),
|
||||
mapSheetAnalDataInferenceGeomEntity.pnu.gt(0),
|
||||
mapSheetAnalDataInferenceGeomEntity.fitState.eq(ImageryFitStatus.UNFIT.getId()),
|
||||
mapSheetAnalDataInferenceGeomEntity.fitStateDttm.lt(nextDayStart),
|
||||
mapSheetAnalDataInferenceGeomEntity.labelState.isNull())
|
||||
.where(
|
||||
mapSheetAnalInferenceEntity.uuid.eq(uuid),
|
||||
lastId == null ? null : mapSheetAnalDataInferenceGeomEntity.geoUid.gt(lastId))
|
||||
.orderBy(mapSheetAnalDataInferenceGeomEntity.mapSheetNum.asc())
|
||||
.limit(totalCnt)
|
||||
.fetch();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long findAllocateAddCnt(UUID uuid, LocalDate baseDate) {
|
||||
ZoneId zone = ZoneId.of("Asia/Seoul"); // 기준 타임존 명확히
|
||||
ZonedDateTime nextDayStart = baseDate.plusDays(1).atStartOfDay(zone);
|
||||
|
||||
return queryFactory
|
||||
.select(mapSheetAnalDataInferenceGeomEntity.geoUid.count())
|
||||
.from(mapSheetAnalInferenceEntity)
|
||||
.innerJoin(mapSheetAnalDataInferenceEntity)
|
||||
.on(mapSheetAnalInferenceEntity.id.eq(mapSheetAnalDataInferenceEntity.analUid))
|
||||
.innerJoin(mapSheetAnalDataInferenceGeomEntity)
|
||||
.on(
|
||||
mapSheetAnalDataInferenceEntity.id.eq(mapSheetAnalDataInferenceGeomEntity.dataUid),
|
||||
mapSheetAnalDataInferenceGeomEntity.pnu.gt(0),
|
||||
mapSheetAnalDataInferenceGeomEntity.fitState.eq(ImageryFitStatus.UNFIT.getId()),
|
||||
mapSheetAnalDataInferenceGeomEntity.fitStateDttm.lt(nextDayStart),
|
||||
mapSheetAnalDataInferenceGeomEntity.labelState.isNull())
|
||||
.where(mapSheetAnalInferenceEntity.uuid.eq(uuid))
|
||||
.fetchOne();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,6 +120,7 @@ public class TrainingDataLabelRepositoryImpl extends QuerydslRepositorySupport
|
||||
.orderBy(
|
||||
mapSheetAnalInferenceEntity.targetYyyy.asc(),
|
||||
mapSheetAnalInferenceEntity.compareYyyy.asc(),
|
||||
labelingAssignmentEntity.assignGroupId.asc(),
|
||||
labelingAssignmentEntity.createdDate.asc(),
|
||||
labelingAssignmentEntity.inferenceGeomUid.asc())
|
||||
.fetch();
|
||||
@@ -641,6 +642,7 @@ public class TrainingDataLabelRepositoryImpl extends QuerydslRepositorySupport
|
||||
queryFactory
|
||||
.select(
|
||||
labelingAssignmentEntity.assignmentUid,
|
||||
labelingAssignmentEntity.assignGroupId,
|
||||
labelingAssignmentEntity.createdDate,
|
||||
labelingAssignmentEntity.inferenceGeomUid,
|
||||
mapSheetAnalInferenceEntity.targetYyyy,
|
||||
@@ -659,6 +661,7 @@ public class TrainingDataLabelRepositoryImpl extends QuerydslRepositorySupport
|
||||
.orderBy(
|
||||
mapSheetAnalInferenceEntity.targetYyyy.asc(),
|
||||
mapSheetAnalInferenceEntity.compareYyyy.asc(),
|
||||
labelingAssignmentEntity.assignGroupId.asc(),
|
||||
labelingAssignmentEntity.createdDate.asc(),
|
||||
labelingAssignmentEntity.inferenceGeomUid.asc())
|
||||
.limit(1)
|
||||
@@ -673,6 +676,7 @@ public class TrainingDataLabelRepositoryImpl extends QuerydslRepositorySupport
|
||||
Long inferenceGeomUid = firstAssigned.get(labelingAssignmentEntity.inferenceGeomUid);
|
||||
Integer targetYyyy = firstAssigned.get(mapSheetAnalInferenceEntity.targetYyyy);
|
||||
Integer compareYyyy = firstAssigned.get(mapSheetAnalInferenceEntity.compareYyyy);
|
||||
String assignGroupId = firstAssigned.get(labelingAssignmentEntity.assignGroupId);
|
||||
|
||||
BooleanExpression beforeCondition =
|
||||
mapSheetAnalInferenceEntity
|
||||
@@ -688,12 +692,20 @@ public class TrainingDataLabelRepositoryImpl extends QuerydslRepositorySupport
|
||||
.targetYyyy
|
||||
.eq(targetYyyy)
|
||||
.and(mapSheetAnalInferenceEntity.compareYyyy.eq(compareYyyy))
|
||||
.and(labelingAssignmentEntity.assignGroupId.lt(assignGroupId)))
|
||||
.or(
|
||||
mapSheetAnalInferenceEntity
|
||||
.targetYyyy
|
||||
.eq(targetYyyy)
|
||||
.and(mapSheetAnalInferenceEntity.compareYyyy.eq(compareYyyy))
|
||||
.and(labelingAssignmentEntity.assignGroupId.eq(assignGroupId))
|
||||
.and(labelingAssignmentEntity.createdDate.lt(createdDttm)))
|
||||
.or(
|
||||
mapSheetAnalInferenceEntity
|
||||
.targetYyyy
|
||||
.eq(targetYyyy)
|
||||
.and(mapSheetAnalInferenceEntity.compareYyyy.eq(compareYyyy))
|
||||
.and(labelingAssignmentEntity.assignGroupId.eq(assignGroupId))
|
||||
.and(labelingAssignmentEntity.createdDate.eq(createdDttm))
|
||||
.and(labelingAssignmentEntity.inferenceGeomUid.lt(inferenceGeomUid)));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user