diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/core/TrainingDataLabelCoreService.java b/src/main/java/com/kamco/cd/kamcoback/postgres/core/TrainingDataLabelCoreService.java index 46288e50..ea14f8dc 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/core/TrainingDataLabelCoreService.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/core/TrainingDataLabelCoreService.java @@ -1,6 +1,7 @@ package com.kamco.cd.kamcoback.postgres.core; import com.kamco.cd.kamcoback.postgres.repository.trainingdata.TrainingDataLabelRepository; +import com.kamco.cd.kamcoback.trainingdata.dto.TrainingDataLabelDto.DefaultPaging; import com.kamco.cd.kamcoback.trainingdata.dto.TrainingDataLabelDto.DetailRes; import com.kamco.cd.kamcoback.trainingdata.dto.TrainingDataLabelDto.GeoFeatureRequest.Properties; import com.kamco.cd.kamcoback.trainingdata.dto.TrainingDataLabelDto.LabelingGeometryInfo; @@ -75,4 +76,8 @@ public class TrainingDataLabelCoreService { public DetailRes getDetail(UUID assignmentUid) { return trainingDataLabelRepository.getDetail(assignmentUid); } + + public DefaultPaging getDefaultPagingNumber(String userId) { + return trainingDataLabelRepository.getDefaultPagingNumber(userId); + } } diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/label/LabelAllocateRepositoryImpl.java b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/label/LabelAllocateRepositoryImpl.java index f2353cea..8bd68ed1 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/label/LabelAllocateRepositoryImpl.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/label/LabelAllocateRepositoryImpl.java @@ -559,8 +559,7 @@ public class LabelAllocateRepositoryImpl implements LabelAllocateRepositoryCusto .select(labelingAssignmentEntity.count()) .from(labelingAssignmentEntity) .where( - analUidCondition, - labelingAssignmentEntity.workState.in("LABEL_FIN", "TEST_ING", "DONE")) + analUidCondition, labelingAssignmentEntity.workState.in("ASSIGNED", "SKIP", "DONE")) .fetchOne(); Long skipCount = @@ -582,7 +581,7 @@ public class LabelAllocateRepositoryImpl implements LabelAllocateRepositoryCusto queryFactory .select(labelingAssignmentEntity.count()) .from(labelingAssignmentEntity) - .where(analUidCondition, labelingAssignmentEntity.workState.eq("DONE")) + .where(analUidCondition, labelingAssignmentEntity.inspectState.eq("COMPLETE")) .fetchOne(); Long inspectorCount = @@ -641,7 +640,7 @@ public class LabelAllocateRepositoryImpl implements LabelAllocateRepositoryCusto .inspectionStatus(inspectionStatus) .inspectionTotalCount(inspectionTotal) .inspectionCompletedCount(inspectCompleted) - .inspectionSkipCount(skipped) + .inspectionSkipCount(skipped) // TODO .inspectionRemainingCount(inspectionRemaining) .inspectorCount(inspectorCount != null ? inspectorCount : 0L) .progressRate(labelingRate) diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/trainingdata/TrainingDataLabelRepositoryCustom.java b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/trainingdata/TrainingDataLabelRepositoryCustom.java index 7e0dd67f..f7121029 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/trainingdata/TrainingDataLabelRepositoryCustom.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/trainingdata/TrainingDataLabelRepositoryCustom.java @@ -1,5 +1,6 @@ package com.kamco.cd.kamcoback.postgres.repository.trainingdata; +import com.kamco.cd.kamcoback.trainingdata.dto.TrainingDataLabelDto.DefaultPaging; import com.kamco.cd.kamcoback.trainingdata.dto.TrainingDataLabelDto.DetailRes; import com.kamco.cd.kamcoback.trainingdata.dto.TrainingDataLabelDto.GeoFeatureRequest.Properties; import com.kamco.cd.kamcoback.trainingdata.dto.TrainingDataLabelDto.LabelingGeometryInfo; @@ -28,4 +29,6 @@ public interface TrainingDataLabelRepositoryCustom { SummaryRes getSummary(String userId); DetailRes getDetail(UUID assignmentUid); + + DefaultPaging getDefaultPagingNumber(String userId); } diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/trainingdata/TrainingDataLabelRepositoryImpl.java b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/trainingdata/TrainingDataLabelRepositoryImpl.java index 4cceef1b..71ed0ea4 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/trainingdata/TrainingDataLabelRepositoryImpl.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/trainingdata/TrainingDataLabelRepositoryImpl.java @@ -8,10 +8,12 @@ import static com.kamco.cd.kamcoback.postgres.entity.QMapSheetLearnDataGeomEntit import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.LabelState; import com.kamco.cd.kamcoback.postgres.entity.LabelingAssignmentEntity; import com.kamco.cd.kamcoback.postgres.entity.MapSheetAnalDataInferenceGeomEntity; import com.kamco.cd.kamcoback.trainingdata.dto.TrainingDataLabelDto.ChangeDetectionInfo; import com.kamco.cd.kamcoback.trainingdata.dto.TrainingDataLabelDto.ClassificationInfo; +import com.kamco.cd.kamcoback.trainingdata.dto.TrainingDataLabelDto.DefaultPaging; import com.kamco.cd.kamcoback.trainingdata.dto.TrainingDataLabelDto.DetailRes; import com.kamco.cd.kamcoback.trainingdata.dto.TrainingDataLabelDto.GeoFeatureRequest.Properties; import com.kamco.cd.kamcoback.trainingdata.dto.TrainingDataLabelDto.InferenceDataGeometry; @@ -23,6 +25,7 @@ import com.kamco.cd.kamcoback.trainingdata.dto.TrainingDataLabelDto.LearnDataGeo import com.kamco.cd.kamcoback.trainingdata.dto.TrainingDataLabelDto.LearnDataGeometry.LearnProperties; import com.kamco.cd.kamcoback.trainingdata.dto.TrainingDataLabelDto.SummaryRes; import com.kamco.cd.kamcoback.trainingdata.dto.TrainingDataLabelDto.searchReq; +import com.querydsl.core.Tuple; import com.querydsl.core.types.Projections; import com.querydsl.core.types.dsl.BooleanExpression; import com.querydsl.core.types.dsl.CaseBuilder; @@ -32,11 +35,13 @@ import com.querydsl.core.types.dsl.StringExpression; import com.querydsl.jpa.impl.JPAQueryFactory; import jakarta.persistence.EntityNotFoundException; import java.time.LocalDate; +import java.time.ZoneId; import java.time.ZonedDateTime; import java.util.List; import java.util.Objects; import java.util.Optional; import java.util.UUID; +import lombok.extern.slf4j.Slf4j; import org.locationtech.jts.geom.Geometry; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; @@ -44,6 +49,7 @@ import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.support.QuerydslRepositorySupport; +@Slf4j public class TrainingDataLabelRepositoryImpl extends QuerydslRepositorySupport implements TrainingDataLabelRepositoryCustom { @@ -57,6 +63,24 @@ public class TrainingDataLabelRepositoryImpl extends QuerydslRepositorySupport @Override public Page findLabelingAssignedList( searchReq searchReq, String userId, String status) { + + // 완료된 라벨은 오늘만, 나머지는 전체 조회 + LocalDate today = LocalDate.now(ZoneId.of("Asia/Seoul")); + ZonedDateTime start = today.atStartOfDay(ZoneId.of("Asia/Seoul")); + ZonedDateTime end = start.plusDays(1); + + BooleanExpression doneToday = + labelingAssignmentEntity + .workState + .eq(LabelState.DONE.getId()) + .and(labelingAssignmentEntity.workStatDttm.goe(start)) + .and(labelingAssignmentEntity.workStatDttm.lt(end)); + + BooleanExpression assignedOrSkip = + labelingAssignmentEntity.workState.in(LabelState.SKIP.getId(), LabelState.ASSIGNED.getId()); + + BooleanExpression dayStateCondition = doneToday.or(assignedOrSkip); + Pageable pageable = PageRequest.of(searchReq.getPage(), searchReq.getSize()); List list = queryFactory @@ -77,12 +101,14 @@ public class TrainingDataLabelRepositoryImpl extends QuerydslRepositorySupport mapSheetAnalDataInferenceGeomEntity.geoUid)) .innerJoin(mapInkx5kEntity) .on(labelingAssignmentEntity.assignGroupId.eq(mapInkx5kEntity.mapidcdNo)) - .where(labelingAssignmentEntity.workerUid.eq(userId), statusInLabelState(status)) + .where(labelingAssignmentEntity.workerUid.eq(userId), dayStateCondition) .offset(pageable.getOffset()) .limit(pageable.getPageSize()) .orderBy( - labelingAssignmentEntity.assignGroupId.asc(), - labelingAssignmentEntity.inferenceGeomUid.asc()) + labelingAssignmentEntity.createdDate.asc(), + labelingAssignmentEntity.inferenceGeomUid + .asc() // 008288b5-5911-41d5-b8fc-b8c8f33d5434 / 362 + ) .fetch(); Long count = @@ -96,8 +122,7 @@ public class TrainingDataLabelRepositoryImpl extends QuerydslRepositorySupport mapSheetAnalDataInferenceGeomEntity.geoUid)) .innerJoin(mapInkx5kEntity) .on(labelingAssignmentEntity.assignGroupId.eq(mapInkx5kEntity.mapidcdNo)) - .where( - labelingAssignmentEntity.workerUid.eq(userId), statusInLabelState(status)) + .where(labelingAssignmentEntity.workerUid.eq(userId), dayStateCondition) .fetchOne()) .orElse(0L); @@ -534,6 +559,72 @@ public class TrainingDataLabelRepositoryImpl extends QuerydslRepositorySupport } } + @Override + public DefaultPaging getDefaultPagingNumber(String userId) { + + ZoneId KST = ZoneId.of("Asia/Seoul"); + ZonedDateTime todayStart = ZonedDateTime.now(KST).toLocalDate().atStartOfDay(KST); + ZonedDateTime todayEnd = todayStart.plusDays(1); + + BooleanExpression doneToday = + labelingAssignmentEntity + .workState + .eq(LabelState.DONE.getId()) + .and(labelingAssignmentEntity.workStatDttm.goe(todayStart)) + .and(labelingAssignmentEntity.workStatDttm.lt(todayEnd)); + + BooleanExpression assignedOrSkip = + labelingAssignmentEntity.workState.in(LabelState.SKIP.getId(), LabelState.ASSIGNED.getId()); + + BooleanExpression stateCondition = doneToday.or(assignedOrSkip); + + Tuple firstAssigned = + queryFactory + .select( + labelingAssignmentEntity.assignmentUid, + labelingAssignmentEntity.createdDate, + labelingAssignmentEntity.inferenceGeomUid) + .from(labelingAssignmentEntity) + .where( + labelingAssignmentEntity.workerUid.eq(userId), + stateCondition, + labelingAssignmentEntity.workState.eq(LabelState.ASSIGNED.getId())) + .orderBy( + labelingAssignmentEntity.createdDate.asc(), + labelingAssignmentEntity.inferenceGeomUid.asc()) + .limit(1) + .fetchOne(); + + if (firstAssigned == null) { + return DefaultPaging.builder().page(0).assignmentUid(null).build(); + } + + UUID firstAssignedUid = firstAssigned.get(labelingAssignmentEntity.assignmentUid); + ZonedDateTime createdDttm = firstAssigned.get(labelingAssignmentEntity.createdDate); + Long inferenceGeomUid = firstAssigned.get(labelingAssignmentEntity.inferenceGeomUid); + + BooleanExpression beforeCondition = + labelingAssignmentEntity + .createdDate + .lt(createdDttm) + .or( + labelingAssignmentEntity + .createdDate + .eq(createdDttm) + .and(labelingAssignmentEntity.inferenceGeomUid.lt(inferenceGeomUid))); + + Long beforeCnt = + queryFactory + .select(labelingAssignmentEntity.count()) + .from(labelingAssignmentEntity) + .where( + labelingAssignmentEntity.workerUid.eq(userId), beforeCondition.and(stateCondition)) + .fetchOne(); + + int page = (int) (beforeCnt / 20); // 기본 사이즈 20 + return DefaultPaging.builder().page(page).assignmentUid(firstAssignedUid).build(); + } + private StringExpression makeCogUrl(NumberPath year) { return new CaseBuilder() .when(imageryEntity.year.eq(year)) diff --git a/src/main/java/com/kamco/cd/kamcoback/trainingdata/TrainingDataLabelApiController.java b/src/main/java/com/kamco/cd/kamcoback/trainingdata/TrainingDataLabelApiController.java index e47db299..5379faeb 100644 --- a/src/main/java/com/kamco/cd/kamcoback/trainingdata/TrainingDataLabelApiController.java +++ b/src/main/java/com/kamco/cd/kamcoback/trainingdata/TrainingDataLabelApiController.java @@ -9,6 +9,7 @@ import com.kamco.cd.kamcoback.trainingdata.dto.TrainingDataLabelDto.LabelingList import com.kamco.cd.kamcoback.trainingdata.service.TrainingDataLabelService; import io.swagger.v3.oas.annotations.Hidden; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; @@ -157,4 +158,24 @@ public class TrainingDataLabelApiController { java.util.UUID assignmentUid) { return ApiResponseDto.ok(trainingDataLabelService.getDetail(assignmentUid)); } + + @Operation(summary = "라벨러 기본 page number 제공", description = "라벨러 기본 page number 제공") + @ApiResponses( + value = { + @ApiResponse( + responseCode = "200", + description = "조회 성공", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = TrainingDataLabelDto.DetailRes.class))), + @ApiResponse(responseCode = "400", description = "잘못된 요청", content = @Content), + @ApiResponse(responseCode = "404", description = "데이터를 찾을 수 없음", content = @Content), + @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) + }) + @GetMapping("/default-page") + public ApiResponseDto getDefaultPagingNumber( + @Parameter(description = "사번", example = "01022223333") @RequestParam String userId) { + return ApiResponseDto.ok(trainingDataLabelService.getDefaultPagingNumber(userId)); + } } diff --git a/src/main/java/com/kamco/cd/kamcoback/trainingdata/dto/TrainingDataLabelDto.java b/src/main/java/com/kamco/cd/kamcoback/trainingdata/dto/TrainingDataLabelDto.java index e56f647e..8671e324 100644 --- a/src/main/java/com/kamco/cd/kamcoback/trainingdata/dto/TrainingDataLabelDto.java +++ b/src/main/java/com/kamco/cd/kamcoback/trainingdata/dto/TrainingDataLabelDto.java @@ -382,4 +382,16 @@ public class TrainingDataLabelDto { @Schema(description = "오늘 완료 건수", example = "0") private Long todayCnt; } + + @Schema(name = "DefaultPaging", description = "페이징 기본 number, uuid 전달") + @Getter + @Setter + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class DefaultPaging { + + private int page; + private UUID assignmentUid; + } } diff --git a/src/main/java/com/kamco/cd/kamcoback/trainingdata/service/TrainingDataLabelService.java b/src/main/java/com/kamco/cd/kamcoback/trainingdata/service/TrainingDataLabelService.java index ff7f1468..140a28ca 100644 --- a/src/main/java/com/kamco/cd/kamcoback/trainingdata/service/TrainingDataLabelService.java +++ b/src/main/java/com/kamco/cd/kamcoback/trainingdata/service/TrainingDataLabelService.java @@ -3,6 +3,7 @@ package com.kamco.cd.kamcoback.trainingdata.service; import com.kamco.cd.kamcoback.config.api.ApiResponseDto.ApiResponseCode; import com.kamco.cd.kamcoback.config.api.ApiResponseDto.ResponseObj; import com.kamco.cd.kamcoback.postgres.core.TrainingDataLabelCoreService; +import com.kamco.cd.kamcoback.trainingdata.dto.TrainingDataLabelDto.DefaultPaging; import com.kamco.cd.kamcoback.trainingdata.dto.TrainingDataLabelDto.DetailRes; import com.kamco.cd.kamcoback.trainingdata.dto.TrainingDataLabelDto.GeoFeatureRequest; import com.kamco.cd.kamcoback.trainingdata.dto.TrainingDataLabelDto.LabelingGeometryInfo; @@ -83,4 +84,8 @@ public class TrainingDataLabelService { public DetailRes getDetail(UUID assignmentUid) { return trainingDataLabelCoreService.getDetail(assignmentUid); } + + public DefaultPaging getDefaultPagingNumber(String userId) { + return trainingDataLabelCoreService.getDefaultPagingNumber(userId); + } }