Merge pull request 'learn 테이블 연결 소스 삭제 및 수정' (#155) from feat/dev_251201 into develop

Reviewed-on: https://kamco.gitea.gs.dabeeo.com/dabeeo/kamco-dabeeo-backoffice/pulls/155
This commit is contained in:
2026-01-07 14:37:57 +09:00
20 changed files with 244 additions and 2659 deletions

View File

@@ -5,7 +5,7 @@ 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.LabelerDetail;
import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.LabelingStatDto;
import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.MoveUserList;
import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.MoveInfo;
import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.UserList;
import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.searchReq;
import com.kamco.cd.kamcoback.label.dto.WorkerStatsDto.ProjectInfo;
@@ -128,7 +128,16 @@ public class LabelAllocateCoreService {
return labelAllocateRepository.findInspectorDetail(userId, uuid);
}
public List<MoveUserList> moveAvailUserList(String userId, String uuid) {
public MoveInfo moveAvailUserList(String userId, String uuid) {
return labelAllocateRepository.moveAvailUserList(userId, uuid);
}
public void insertLabelerUser(Long analUid, String userId, int demand) {
labelAllocateRepository.insertLabelerUser(analUid, userId, demand);
}
public void assignOwnerReAllocate(
String uuid, String userId, String paramUserId, Long assignCount) {
labelAllocateRepository.assignOwnerReAllocate(uuid, userId, paramUserId, assignCount);
}
}

View File

@@ -0,0 +1,48 @@
package com.kamco.cd.kamcoback.postgres.entity;
import com.kamco.cd.kamcoback.label.dto.LabelLabelerDto;
import com.kamco.cd.kamcoback.postgres.CommonDateEntity;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import java.util.UUID;
@Entity
@Table(name = "tb_labeling_labeler")
public class LabelingLabelerEntity extends CommonDateEntity {
@Id
@Column(name = "lb_usr_uid")
private UUID lbUsrUid;
@Column(name = "anal_uid")
private Long analUid;
@Column(name = "worker_uid")
private String workerUid;
private Long allocateCnt;
private Boolean deleted;
private Boolean reAllocateYn;
private Long reAllocateCnt;
private String reAllocateWorkerUid;
public LabelLabelerDto.Basic toDto() {
return new LabelLabelerDto.Basic(
this.lbUsrUid,
this.analUid,
this.workerUid,
this.allocateCnt,
this.deleted,
this.reAllocateYn,
this.reAllocateCnt,
this.reAllocateWorkerUid,
super.getCreatedDate(),
super.getModifiedDate());
}
}

View File

@@ -1,66 +0,0 @@
package com.kamco.cd.kamcoback.postgres.repository;
import com.kamco.cd.kamcoback.postgres.entity.MapSheetLearnDataGeomEntity;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
@Repository
public interface MapSheetLearnDataGeomRepository
extends JpaRepository<MapSheetLearnDataGeomEntity, Long> {
/** 데이터 UID로 지오메트리 정보 조회 */
List<MapSheetLearnDataGeomEntity> findByDataUid(Long dataUid);
/** 도엽 번호로 지오메트리 정보 조회 */
List<MapSheetLearnDataGeomEntity> findByMapSheetNum(Long mapSheetNum);
/** 연도 범위로 지오메트리 정보 조회 */
List<MapSheetLearnDataGeomEntity> findByBeforeYyyyAndAfterYyyy(
Integer beforeYyyy, Integer afterYyyy);
/** 지오메트리 타입별 조회 */
List<MapSheetLearnDataGeomEntity> findByGeoType(String geoType);
/** 데이터 UID로 기존 지오메트리 데이터 삭제 (재생성 전에 사용) */
void deleteByDataUid(Long dataUid);
/** PostGIS 함수를 사용하여 geometry 데이터를 직접 삽입 ST_SetSRID(ST_GeomFromGeoJSON(...), 5186) 형식으로 저장 */
@Modifying
@Transactional
@Query(
value =
"""
INSERT INTO tb_map_sheet_learn_data_geom (
geo_uid, cd_prob, class_before_name, class_before_prob,
class_after_name, class_after_prob, map_sheet_num,
before_yyyy, after_yyyy, area, geom, geo_type, data_uid,
created_dttm, updated_dttm
) VALUES (
:geoUid, :cdProb, :classBeforeName, :classBeforeProb,
:classAfterName, :classAfterProb, :mapSheetNum,
:beforeYyyy, :afterYyyy, :area,
ST_SetSRID(ST_GeomFromGeoJSON(CAST(:geometryJson AS TEXT)), 5186),
:geoType, :dataUid, NOW(), NOW()
) ON CONFLICT (geo_uid) DO NOTHING
""",
nativeQuery = true)
void insertWithPostGISGeometry(
@Param("geoUid") Long geoUid,
@Param("cdProb") Double cdProb,
@Param("classBeforeName") String classBeforeName,
@Param("classBeforeProb") Double classBeforeProb,
@Param("classAfterName") String classAfterName,
@Param("classAfterProb") Double classAfterProb,
@Param("mapSheetNum") Long mapSheetNum,
@Param("beforeYyyy") Integer beforeYyyy,
@Param("afterYyyy") Integer afterYyyy,
@Param("area") Double area,
@Param("geometryJson") String geometryJson,
@Param("geoType") String geoType,
@Param("dataUid") Long dataUid);
}

View File

@@ -1,32 +0,0 @@
package com.kamco.cd.kamcoback.postgres.repository;
import com.kamco.cd.kamcoback.postgres.entity.MapSheetLearnDataEntity;
import java.util.List;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface MapSheetLearnDataRepository extends JpaRepository<MapSheetLearnDataEntity, Long> {
/** 데이터 이름으로 조회 */
Optional<MapSheetLearnDataEntity> findByDataName(String dataName);
/** 데이터 경로로 조회 */
Optional<MapSheetLearnDataEntity> findByDataPath(String dataPath);
/** 처리 상태별 조회 */
List<MapSheetLearnDataEntity> findByDataState(String dataState);
/** 데이터 타입별 조회 */
List<MapSheetLearnDataEntity> findByDataType(String dataType);
/** 분석 상태별 조회 */
List<MapSheetLearnDataEntity> findByAnalState(String analState);
/** 분석 상태별 개수 조회 */
long countByAnalState(String analState);
/** 처리되지 않은 데이터 조회 (data_state가 'PENDING' 또는 null인 것들) */
List<MapSheetLearnDataEntity> findByDataStateIsNullOrDataState(String dataState);
}

View File

@@ -5,7 +5,7 @@ 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.LabelerDetail;
import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.LabelingStatDto;
import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.MoveUserList;
import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.MoveInfo;
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;
@@ -78,5 +78,9 @@ public interface LabelAllocateRepositoryCustom {
LabelerDetail findInspectorDetail(String userId, String uuid);
List<MoveUserList> moveAvailUserList(String userId, String uuid);
MoveInfo moveAvailUserList(String userId, String uuid);
void insertLabelerUser(Long analUid, String userId, int demand);
void assignOwnerReAllocate(String uuid, String userId, String paramUserId, Long assignCount);
}

View File

@@ -2,6 +2,7 @@ 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.QLabelingInspectorEntity.labelingInspectorEntity;
import static com.kamco.cd.kamcoback.postgres.entity.QLabelingLabelerEntity.labelingLabelerEntity;
import static com.kamco.cd.kamcoback.postgres.entity.QMapSheetAnalDataInferenceGeomEntity.mapSheetAnalDataInferenceGeomEntity;
import static com.kamco.cd.kamcoback.postgres.entity.QMapSheetAnalInferenceEntity.mapSheetAnalInferenceEntity;
import static com.kamco.cd.kamcoback.postgres.entity.QMemberEntity.memberEntity;
@@ -13,6 +14,7 @@ import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.InspectState;
import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.LabelState;
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.MoveInfo;
import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.MoveUserList;
import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.UserList;
import com.kamco.cd.kamcoback.label.dto.WorkerStatsDto.ProjectInfo;
@@ -68,7 +70,8 @@ public class LabelAllocateRepositoryImpl implements LabelAllocateRepositoryCusto
Projections.constructor(
AllocateInfoDto.class,
mapSheetAnalDataInferenceGeomEntity.geoUid,
mapSheetAnalDataInferenceGeomEntity.mapSheetNum))
mapSheetAnalDataInferenceGeomEntity.mapSheetNum,
mapSheetAnalDataInferenceGeomEntity.pnu))
.from(mapSheetAnalDataInferenceGeomEntity)
.where(
lastId == null ? null : mapSheetAnalDataInferenceGeomEntity.geoUid.gt(lastId),
@@ -116,8 +119,8 @@ public class LabelAllocateRepositoryImpl implements LabelAllocateRepositoryCusto
"""
insert into tb_labeling_assignment
(assignment_uid, inference_geom_uid, worker_uid,
work_state, assign_group_id, anal_uid)
values (?, ?, ?, ?, ?, ?)
work_state, assign_group_id, anal_uid, pnu)
values (?, ?, ?, ?, ?, ?, ?)
""";
try (PreparedStatement ps = connection.prepareStatement(sql)) {
@@ -130,6 +133,7 @@ public class LabelAllocateRepositoryImpl implements LabelAllocateRepositoryCusto
ps.setString(4, LabelState.ASSIGNED.getId());
ps.setString(5, String.valueOf(info.getMapSheetNum()));
ps.setLong(6, analEntity.getId());
ps.setLong(7, info.getPnu());
ps.addBatch();
batchSize++;
@@ -1038,12 +1042,16 @@ public class LabelAllocateRepositoryImpl implements LabelAllocateRepositoryCusto
}
@Override
public List<MoveUserList> moveAvailUserList(String userId, String uuid) {
public MoveInfo moveAvailUserList(String userId, String uuid) {
NumberExpression<Long> totalCnt = labelingAssignmentEntity.count();
NumberExpression<Long> completeCnt =
new CaseBuilder()
.when(labelingAssignmentEntity.workState.eq(LabelState.COMPLETE.getId()))
.when(
labelingAssignmentEntity
.workState
.eq(LabelState.COMPLETE.getId())
.or(labelingAssignmentEntity.workState.eq(LabelState.SKIP.getId())))
.then(1L)
.otherwise(0L)
.sum();
@@ -1073,24 +1081,78 @@ public class LabelAllocateRepositoryImpl implements LabelAllocateRepositoryCusto
throw new EntityNotFoundException("MapSheetAnalInferenceEntity not found for analUid: ");
}
return queryFactory
.select(
Projections.constructor(
MoveUserList.class,
memberEntity.userRole,
memberEntity.employeeNo,
memberEntity.name,
remainCnt,
percent))
.from(labelingAssignmentEntity)
.innerJoin(memberEntity)
.on(labelingAssignmentEntity.workerUid.eq(memberEntity.employeeNo))
Long userChargeCnt =
queryFactory
.select(labelingAssignmentEntity.inferenceGeomUid.count())
.from(labelingAssignmentEntity)
.where(
labelingAssignmentEntity.analUid.eq(analEntity.getId()),
labelingAssignmentEntity.workerUid.eq(userId),
labelingAssignmentEntity.workState.eq(LabelState.ASSIGNED.getId()))
.fetchOne();
List<MoveUserList> list =
queryFactory
.select(
Projections.constructor(
MoveUserList.class,
memberEntity.userRole,
memberEntity.employeeNo,
memberEntity.name,
remainCnt,
percent))
.from(labelingLabelerEntity)
.innerJoin(memberEntity)
.on(labelingAssignmentEntity.workerUid.eq(memberEntity.employeeNo))
.where(
labelingAssignmentEntity.analUid.eq(analEntity.getId()),
labelingAssignmentEntity.workerUid.ne(userId))
.groupBy(memberEntity.userRole, memberEntity.employeeNo, memberEntity.name)
.having(
completeCnt
.multiply(2)
.goe(totalCnt)) // 진행률 평균 이상인 것들만 조회 => percent 를 바로 쓰면 having절에 무리가 갈 수 있다고 함
.orderBy(completeCnt.desc()) // TODO: 도엽번호? PNU? 로 정렬하여 보여주기?
.fetch();
return new MoveInfo(userChargeCnt, list);
}
@Override
public void insertLabelerUser(Long analUid, String userId, int demand) {
queryFactory
.insert(labelingLabelerEntity)
.columns(
labelingLabelerEntity.lbUsrUid,
labelingLabelerEntity.analUid,
labelingLabelerEntity.workerUid,
labelingLabelerEntity.allocateCnt)
.values(UUID.randomUUID(), analUid, userId, demand)
.execute();
}
@Override
public void assignOwnerReAllocate(
String uuid, String userId, String paramUserId, Long assignCount) {
// analUid로 분석 정보 조회
MapSheetAnalInferenceEntity analEntity =
queryFactory
.selectFrom(mapSheetAnalInferenceEntity)
.where(mapSheetAnalInferenceEntity.uuid.eq(UUID.fromString(uuid)))
.fetchOne();
if (Objects.isNull(analEntity)) {
throw new EntityNotFoundException("MapSheetAnalInferenceEntity not found for analUid: ");
}
queryFactory
.update(labelingLabelerEntity)
.set(labelingLabelerEntity.reAllocateYn, true)
.set(labelingLabelerEntity.reAllocateWorkerUid, userId)
.set(labelingLabelerEntity.reAllocateCnt, assignCount)
.where(
labelingAssignmentEntity.analUid.eq(analEntity.getId()),
labelingAssignmentEntity.workerUid.ne(userId))
.groupBy(memberEntity.userRole, memberEntity.employeeNo, memberEntity.name)
.having(completeCnt.multiply(2).goe(totalCnt)) // 진행률 평균 이상인 것들만 조회 => percent 를 바로 쓰면
.orderBy(completeCnt.desc())
.fetch();
labelingLabelerEntity.analUid.eq(analEntity.getId()),
labelingLabelerEntity.workerUid.eq(paramUserId))
.execute();
}
}