라벨 다운로드 확인 API 추가
This commit is contained in:
@@ -31,6 +31,7 @@ import java.util.List;
|
|||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.coyote.BadRequestException;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
@@ -366,7 +367,7 @@ public class LabelAllocateApiController {
|
|||||||
@Schema(
|
@Schema(
|
||||||
type = "string",
|
type = "string",
|
||||||
format = "uuid",
|
format = "uuid",
|
||||||
example = "69c4e56c-e0bf-4742-9225-bba9aae39052"))
|
example = "6d8d49dc-0c9d-4124-adc7-b9ca610cc394"))
|
||||||
})
|
})
|
||||||
@ApiResponses(
|
@ApiResponses(
|
||||||
value = {
|
value = {
|
||||||
@@ -382,9 +383,13 @@ public class LabelAllocateApiController {
|
|||||||
})
|
})
|
||||||
@GetMapping("/download/{uuid}")
|
@GetMapping("/download/{uuid}")
|
||||||
public ResponseEntity<StreamingResponseBody> download(
|
public ResponseEntity<StreamingResponseBody> download(
|
||||||
@Parameter(example = "69c4e56c-e0bf-4742-9225-bba9aae39052") @PathVariable UUID uuid)
|
@Parameter(example = "6d8d49dc-0c9d-4124-adc7-b9ca610cc394") @PathVariable UUID uuid)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
|
|
||||||
|
if (!labelAllocateService.isDownloadable(uuid)) {
|
||||||
|
throw new BadRequestException();
|
||||||
|
}
|
||||||
|
|
||||||
String uid = labelAllocateService.findLearnUid(uuid);
|
String uid = labelAllocateService.findLearnUid(uuid);
|
||||||
Path zipPath = Paths.get(responsePath).resolve(uid + ".zip");
|
Path zipPath = Paths.get(responsePath).resolve(uid + ".zip");
|
||||||
|
|
||||||
@@ -407,7 +412,7 @@ public class LabelAllocateApiController {
|
|||||||
@ApiResponse(responseCode = "500", description = "서버 오류", content = @Content)
|
@ApiResponse(responseCode = "500", description = "서버 오류", content = @Content)
|
||||||
})
|
})
|
||||||
public ApiResponseDto<Page<AuditLogDto.DownloadRes>> downloadAudit(
|
public ApiResponseDto<Page<AuditLogDto.DownloadRes>> downloadAudit(
|
||||||
@Parameter(description = "UUID", example = "69c4e56c-e0bf-4742-9225-bba9aae39052")
|
@Parameter(description = "UUID", example = "6d8d49dc-0c9d-4124-adc7-b9ca610cc394")
|
||||||
@PathVariable
|
@PathVariable
|
||||||
UUID uuid,
|
UUID uuid,
|
||||||
// @Parameter(description = "다운로드일 시작", example = "2025-01-01") @RequestParam(required =
|
// @Parameter(description = "다운로드일 시작", example = "2025-01-01") @RequestParam(required =
|
||||||
@@ -435,4 +440,25 @@ public class LabelAllocateApiController {
|
|||||||
|
|
||||||
return ApiResponseDto.ok(labelAllocateService.getDownloadAudit(searchReq, downloadReq));
|
return ApiResponseDto.ok(labelAllocateService.getDownloadAudit(searchReq, downloadReq));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "다운로드 가능여부 조회", description = "다운로드 가능여부 조회 API")
|
||||||
|
@GetMapping(value = "/download-check/{uuid}")
|
||||||
|
@ApiResponses(
|
||||||
|
value = {
|
||||||
|
@ApiResponse(
|
||||||
|
responseCode = "200",
|
||||||
|
description = "검색 성공",
|
||||||
|
content =
|
||||||
|
@Content(
|
||||||
|
mediaType = "application/json",
|
||||||
|
schema = @Schema(implementation = Page.class))),
|
||||||
|
@ApiResponse(responseCode = "400", description = "잘못된 검색 조건", content = @Content),
|
||||||
|
@ApiResponse(responseCode = "500", description = "서버 오류", content = @Content)
|
||||||
|
})
|
||||||
|
public ApiResponseDto<Boolean> isDownloadable(
|
||||||
|
@Parameter(description = "UUID", example = "6d8d49dc-0c9d-4124-adc7-b9ca610cc394")
|
||||||
|
@PathVariable
|
||||||
|
UUID uuid) {
|
||||||
|
return ApiResponseDto.ok(labelAllocateService.isDownloadable(uuid));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -359,4 +359,15 @@ public class LabelAllocateDto {
|
|||||||
@Schema(description = "작업기간 종료일")
|
@Schema(description = "작업기간 종료일")
|
||||||
private ZonedDateTime projectCloseDttm;
|
private ZonedDateTime projectCloseDttm;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
public static class InferenceLearnDto {
|
||||||
|
private UUID analUuid;
|
||||||
|
private String learnUid;
|
||||||
|
private String analState;
|
||||||
|
private Long analId;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -290,4 +290,14 @@ public class LabelAllocateService {
|
|||||||
AuditLogDto.searchReq searchReq, DownloadReq downloadReq) {
|
AuditLogDto.searchReq searchReq, DownloadReq downloadReq) {
|
||||||
return auditLogCoreService.findLogByAccount(searchReq, downloadReq);
|
return auditLogCoreService.findLogByAccount(searchReq, downloadReq);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 다운로드 가능 여부 조회
|
||||||
|
*
|
||||||
|
* @param uuid
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public boolean isDownloadable(UUID uuid) {
|
||||||
|
return labelAllocateCoreService.isDownloadable(uuid);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ import com.kamco.cd.kamcoback.common.exception.CustomApiException;
|
|||||||
import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto;
|
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.AllocateInfoDto;
|
||||||
import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.InferenceDetail;
|
import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.InferenceDetail;
|
||||||
|
import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.InferenceLearnDto;
|
||||||
|
import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.LabelMngState;
|
||||||
import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.LabelerDetail;
|
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.LabelingStatDto;
|
||||||
import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.MoveInfo;
|
import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.MoveInfo;
|
||||||
@@ -14,11 +16,16 @@ 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.WorkProgressInfo;
|
||||||
import com.kamco.cd.kamcoback.label.dto.WorkerStatsDto.WorkerStatistics;
|
import com.kamco.cd.kamcoback.label.dto.WorkerStatsDto.WorkerStatistics;
|
||||||
import com.kamco.cd.kamcoback.postgres.entity.LabelingAssignmentEntity;
|
import com.kamco.cd.kamcoback.postgres.entity.LabelingAssignmentEntity;
|
||||||
|
import com.kamco.cd.kamcoback.postgres.repository.batch.BatchStepHistoryRepository;
|
||||||
import com.kamco.cd.kamcoback.postgres.repository.label.LabelAllocateRepository;
|
import com.kamco.cd.kamcoback.postgres.repository.label.LabelAllocateRepository;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
@@ -28,6 +35,10 @@ import org.springframework.stereotype.Service;
|
|||||||
public class LabelAllocateCoreService {
|
public class LabelAllocateCoreService {
|
||||||
|
|
||||||
private final LabelAllocateRepository labelAllocateRepository;
|
private final LabelAllocateRepository labelAllocateRepository;
|
||||||
|
private final BatchStepHistoryRepository batchStepHistoryRepository;
|
||||||
|
|
||||||
|
@Value("${file.dataset-response}")
|
||||||
|
private String responsePath;
|
||||||
|
|
||||||
public List<AllocateInfoDto> fetchNextIds(Long lastId, Long batchSize, UUID uuid) {
|
public List<AllocateInfoDto> fetchNextIds(Long lastId, Long batchSize, UUID uuid) {
|
||||||
return labelAllocateRepository.fetchNextIds(lastId, batchSize, uuid);
|
return labelAllocateRepository.fetchNextIds(lastId, batchSize, uuid);
|
||||||
@@ -237,6 +248,30 @@ public class LabelAllocateCoreService {
|
|||||||
return labelAllocateRepository.findLabelingIngProcessCnt();
|
return labelAllocateRepository.findLabelingIngProcessCnt();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isDownloadable(UUID uuid) {
|
||||||
|
InferenceLearnDto dto = labelAllocateRepository.findLabelingIngProcessId(uuid);
|
||||||
|
|
||||||
|
if (dto == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 파일이 있는지만 확인
|
||||||
|
Path path = Paths.get(responsePath).resolve(dto.getLearnUid() + ".zip");
|
||||||
|
|
||||||
|
if (!Files.exists(path) || !Files.isRegularFile(path)) {
|
||||||
|
// 실제 파일만 true (디렉터리는 제외)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 다운로드 확인할 학습데이터가 라벨링중인 경우 파일 생성여부가 정상인지 확인
|
||||||
|
if (dto.getAnalState().equals(LabelMngState.ASSIGNED.getId())
|
||||||
|
|| dto.getAnalState().equals(LabelMngState.ING.getId())) {
|
||||||
|
return batchStepHistoryRepository.isDownloadable(dto.getAnalId());
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public String findLearnUid(UUID uuid) {
|
public String findLearnUid(UUID uuid) {
|
||||||
return labelAllocateRepository
|
return labelAllocateRepository
|
||||||
.findLearnUid(uuid)
|
.findLearnUid(uuid)
|
||||||
|
|||||||
@@ -0,0 +1,62 @@
|
|||||||
|
package com.kamco.cd.kamcoback.postgres.entity;
|
||||||
|
|
||||||
|
import jakarta.persistence.Column;
|
||||||
|
import jakarta.persistence.Entity;
|
||||||
|
import jakarta.persistence.GeneratedValue;
|
||||||
|
import jakarta.persistence.GenerationType;
|
||||||
|
import jakarta.persistence.Id;
|
||||||
|
import jakarta.persistence.Table;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
import jakarta.validation.constraints.Size;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@Entity
|
||||||
|
@Table(name = "batch_step_history")
|
||||||
|
public class BatchStepHistoryEntity {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
@Column(name = "id", nullable = false)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Column(name = "anal_uid", nullable = false)
|
||||||
|
private Long analUid;
|
||||||
|
|
||||||
|
@Size(max = 255)
|
||||||
|
@NotNull
|
||||||
|
@Column(name = "result_uid", nullable = false)
|
||||||
|
private String resultUid;
|
||||||
|
|
||||||
|
@Size(max = 100)
|
||||||
|
@NotNull
|
||||||
|
@Column(name = "step_name", nullable = false, length = 100)
|
||||||
|
private String stepName;
|
||||||
|
|
||||||
|
@Size(max = 50)
|
||||||
|
@NotNull
|
||||||
|
@Column(name = "status", nullable = false, length = 50)
|
||||||
|
private String status;
|
||||||
|
|
||||||
|
@Column(name = "error_message", length = Integer.MAX_VALUE)
|
||||||
|
private String errorMessage;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Column(name = "started_dttm", nullable = false)
|
||||||
|
private LocalDateTime startedDttm;
|
||||||
|
|
||||||
|
@Column(name = "completed_dttm")
|
||||||
|
private LocalDateTime completedDttm;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Column(name = "created_dttm", nullable = false)
|
||||||
|
private LocalDateTime createdDttm;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Column(name = "updated_dttm", nullable = false)
|
||||||
|
private LocalDateTime updatedDttm;
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package com.kamco.cd.kamcoback.postgres.repository.batch;
|
||||||
|
|
||||||
|
import com.kamco.cd.kamcoback.postgres.entity.BatchStepHistoryEntity;
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
|
||||||
|
public interface BatchStepHistoryRepository
|
||||||
|
extends JpaRepository<BatchStepHistoryEntity, Long>, BatchStepHistoryRepositoryCustom {}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package com.kamco.cd.kamcoback.postgres.repository.batch;
|
||||||
|
|
||||||
|
public interface BatchStepHistoryRepositoryCustom {
|
||||||
|
boolean isDownloadable(Long analUid);
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
package com.kamco.cd.kamcoback.postgres.repository.batch;
|
||||||
|
|
||||||
|
import com.kamco.cd.kamcoback.postgres.entity.QBatchStepHistoryEntity;
|
||||||
|
import com.querydsl.jpa.impl.JPAQueryFactory;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
@Repository
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class BatchStepHistoryRepositoryImpl implements BatchStepHistoryRepositoryCustom {
|
||||||
|
private final JPAQueryFactory queryFactory;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isDownloadable(Long analUid) {
|
||||||
|
QBatchStepHistoryEntity h = QBatchStepHistoryEntity.batchStepHistoryEntity;
|
||||||
|
|
||||||
|
boolean startedExists =
|
||||||
|
queryFactory
|
||||||
|
.selectOne()
|
||||||
|
.from(h)
|
||||||
|
.where(
|
||||||
|
h.analUid.eq(analUid), h.stepName.eq("zipResponseStep"), h.status.eq("STARTED"))
|
||||||
|
.fetchFirst()
|
||||||
|
!= null;
|
||||||
|
|
||||||
|
boolean successExists =
|
||||||
|
queryFactory
|
||||||
|
.selectOne()
|
||||||
|
.from(h)
|
||||||
|
.where(
|
||||||
|
h.analUid.eq(analUid), h.stepName.eq("zipResponseStep"), h.status.eq("SUCCESS"))
|
||||||
|
.fetchFirst()
|
||||||
|
!= null;
|
||||||
|
|
||||||
|
return successExists && !startedExists;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@ package com.kamco.cd.kamcoback.postgres.repository.label;
|
|||||||
import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto;
|
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.AllocateInfoDto;
|
||||||
import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.InferenceDetail;
|
import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.InferenceDetail;
|
||||||
|
import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.InferenceLearnDto;
|
||||||
import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.LabelerDetail;
|
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.LabelingStatDto;
|
||||||
import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.MoveInfo;
|
import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.MoveInfo;
|
||||||
@@ -106,5 +107,7 @@ public interface LabelAllocateRepositoryCustom {
|
|||||||
|
|
||||||
Long findLabelingIngProcessCnt();
|
Long findLabelingIngProcessCnt();
|
||||||
|
|
||||||
|
InferenceLearnDto findLabelingIngProcessId(UUID uuid);
|
||||||
|
|
||||||
Optional<String> findLearnUid(UUID uuid);
|
Optional<String> findLearnUid(UUID uuid);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import com.kamco.cd.kamcoback.common.enums.StatusType;
|
|||||||
import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto;
|
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.AllocateInfoDto;
|
||||||
import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.InferenceDetail;
|
import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.InferenceDetail;
|
||||||
|
import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.InferenceLearnDto;
|
||||||
import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.InspectState;
|
import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.InspectState;
|
||||||
import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.LabelMngState;
|
import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.LabelMngState;
|
||||||
import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.LabelState;
|
import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.LabelState;
|
||||||
@@ -1827,6 +1828,23 @@ public class LabelAllocateRepositoryImpl implements LabelAllocateRepositoryCusto
|
|||||||
.fetchOne();
|
.fetchOne();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InferenceLearnDto findLabelingIngProcessId(UUID uuid) {
|
||||||
|
return queryFactory
|
||||||
|
.select(
|
||||||
|
Projections.constructor(
|
||||||
|
InferenceLearnDto.class,
|
||||||
|
mapSheetAnalInferenceEntity.uuid,
|
||||||
|
mapSheetLearnEntity.uid,
|
||||||
|
mapSheetAnalInferenceEntity.analState,
|
||||||
|
mapSheetAnalInferenceEntity.id))
|
||||||
|
.from(mapSheetLearnEntity)
|
||||||
|
.join(mapSheetAnalInferenceEntity)
|
||||||
|
.on(mapSheetAnalInferenceEntity.learnId.eq(mapSheetLearnEntity.id))
|
||||||
|
.where(mapSheetAnalInferenceEntity.uuid.eq(uuid))
|
||||||
|
.fetchOne();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<String> findLearnUid(UUID uuid) {
|
public Optional<String> findLearnUid(UUID uuid) {
|
||||||
return Optional.ofNullable(
|
return Optional.ofNullable(
|
||||||
|
|||||||
Reference in New Issue
Block a user