From 701192ecd2e7ffc7db140df528c9889d70f59e7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?dean=5B=EB=B0=B1=EB=B3=91=EB=82=A8=5D?= Date: Mon, 29 Dec 2025 14:47:54 +0900 Subject: [PATCH] feat: polishing --- .../mapsheet/MapSheetMngApiV2Controller.java | 4 +- .../mapsheet/dto/MapSheetMngDto.java | 56 +++++++++++++ .../mapsheet/service/MapSheetMngService.java | 36 +++++++-- .../postgres/core/MapSheetMngCoreService.java | 38 ++++++--- .../postgres/entity/MapSheetMngHstEntity.java | 80 +++++++++++++++++-- .../mapsheet/MapSheetMngRepositoryCustom.java | 4 + .../mapsheet/MapSheetMngRepositoryImpl.java | 53 +++++++----- 7 files changed, 227 insertions(+), 44 deletions(-) diff --git a/src/main/java/com/kamco/cd/kamcoback/mapsheet/MapSheetMngApiV2Controller.java b/src/main/java/com/kamco/cd/kamcoback/mapsheet/MapSheetMngApiV2Controller.java index ed8a92de..9ddf3888 100644 --- a/src/main/java/com/kamco/cd/kamcoback/mapsheet/MapSheetMngApiV2Controller.java +++ b/src/main/java/com/kamco/cd/kamcoback/mapsheet/MapSheetMngApiV2Controller.java @@ -40,9 +40,9 @@ public class MapSheetMngApiV2Controller { @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) }) @GetMapping("/mng-year-list") - public ApiResponseDto findMapSheetMngYyyyList() { + public ApiResponseDto getListMapListYYYYLimit10() { - List years = mapSheetMngService.findMapSheetMngYyyyList(); + List years = mapSheetMngService.getListMapListYYYYLimit10(); // 현재 년도 가져온다 int currentYear = Year.now().getValue(); diff --git a/src/main/java/com/kamco/cd/kamcoback/mapsheet/dto/MapSheetMngDto.java b/src/main/java/com/kamco/cd/kamcoback/mapsheet/dto/MapSheetMngDto.java index 300243b3..3e102248 100644 --- a/src/main/java/com/kamco/cd/kamcoback/mapsheet/dto/MapSheetMngDto.java +++ b/src/main/java/com/kamco/cd/kamcoback/mapsheet/dto/MapSheetMngDto.java @@ -2,12 +2,14 @@ package com.kamco.cd.kamcoback.mapsheet.dto; import com.kamco.cd.kamcoback.common.enums.MngStateType; import com.kamco.cd.kamcoback.common.enums.SyncStateType; +import com.kamco.cd.kamcoback.common.utils.enums.EnumType; import com.kamco.cd.kamcoback.common.utils.enums.Enums; import com.kamco.cd.kamcoback.common.utils.interfaces.JsonFormatDttm; import io.swagger.v3.oas.annotations.media.Schema; import java.time.ZonedDateTime; import java.util.List; import lombok.AllArgsConstructor; +import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; @@ -319,4 +321,58 @@ public class MapSheetMngDto { this.years = years; } } + + @Getter + @AllArgsConstructor + public enum MapSheetState implements EnumType { + // @formatter:off + DONE("완료"), + NOTYET("처리대기"); + // @formatter:on + + private final String message; + + @Override + public String getId() { + return name(); + } + + @Override + public String getText() { + return message; + } + } + + // 연도리스틀 조회시 사용하는 request Dto + @Getter + @Setter + @NoArgsConstructor + public static class YearSearchReq { + + private String status; + + // 페이징 파라미터 + private int page = 0; + private int size = 20; + private String sort; + + @Builder + public YearSearchReq(String status, int page, int size, String sort) { + this.status = status; + this.page = page; + this.size = size; + this.sort = sort; + } + + public Pageable toPageable() { + if (sort != null && !sort.isEmpty()) { + String[] sortParams = sort.split(","); + String property = sortParams[0]; + Sort.Direction direction = + sortParams.length > 1 ? Sort.Direction.fromString(sortParams[1]) : Sort.Direction.ASC; + return PageRequest.of(page, size, Sort.by(direction, property)); + } + return PageRequest.of(page, size); + } + } } diff --git a/src/main/java/com/kamco/cd/kamcoback/mapsheet/service/MapSheetMngService.java b/src/main/java/com/kamco/cd/kamcoback/mapsheet/service/MapSheetMngService.java index ffa25353..9b58855b 100644 --- a/src/main/java/com/kamco/cd/kamcoback/mapsheet/service/MapSheetMngService.java +++ b/src/main/java/com/kamco/cd/kamcoback/mapsheet/service/MapSheetMngService.java @@ -9,7 +9,9 @@ import com.kamco.cd.kamcoback.mapsheet.dto.MapSheetMngDto.ErrorDataDto; import com.kamco.cd.kamcoback.mapsheet.dto.MapSheetMngDto.ErrorSearchReq; import com.kamco.cd.kamcoback.mapsheet.dto.MapSheetMngDto.MngDto; import com.kamco.cd.kamcoback.mapsheet.dto.MapSheetMngDto.MngFilesDto; +import com.kamco.cd.kamcoback.mapsheet.dto.MapSheetMngDto.YearSearchReq; import com.kamco.cd.kamcoback.postgres.core.MapSheetMngCoreService; +import com.kamco.cd.kamcoback.postgres.entity.YearEntity; import jakarta.validation.Valid; import java.io.File; import java.io.IOException; @@ -17,6 +19,7 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardCopyOption; +import java.util.Comparator; import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; @@ -40,6 +43,16 @@ public class MapSheetMngService { return mapSheetMngCoreService.findMapSheetMngYyyyList(); } + public List getListMapListYYYYLimit10() { + + YearSearchReq req = YearSearchReq.builder().status("NOTYET").page(0).size(10).build(); + // List조회 + Page years = mapSheetMngCoreService.getListMapListYYYYWithPaging(req); + return years.map(YearEntity::getYyyy).getContent().stream() + .sorted(Comparator.reverseOrder()) + .toList(); + } + public MngDto findMapSheetMng(int mngYyyy) { return mapSheetMngCoreService.findMapSheetMng(mngYyyy); } @@ -130,10 +143,15 @@ public class MapSheetMngService { if (!overwrite) { if (tfwCnt > 0 || tifCnt > 0) { String tfwtifMsg = ""; - if (tfwCnt > 0) tfwtifMsg = tfwFile.getOriginalFilename(); + if (tfwCnt > 0) { + tfwtifMsg = tfwFile.getOriginalFilename(); + } if (tifCnt > 0) { - if (tfwCnt > 0) tfwtifMsg = "," + tifFile.getOriginalFilename(); - else tfwtifMsg = tifFile.getOriginalFilename(); + if (tfwCnt > 0) { + tfwtifMsg = "," + tifFile.getOriginalFilename(); + } else { + tfwtifMsg = tifFile.getOriginalFilename(); + } } return new DmlReturn("duplicate", tfwtifMsg); } @@ -153,8 +171,12 @@ public class MapSheetMngService { return new DmlReturn("fail", "UPLOAD ERROR"); } - if (!FIleChecker.cmmndGdalInfo(tifTmpPath)) return new DmlReturn("fail", "TIF TYPE ERROR"); - if (!FIleChecker.checkTfw(tfwTmpPath)) return new DmlReturn("fail", "TFW TYPE ERROR"); + if (!FIleChecker.cmmndGdalInfo(tifTmpPath)) { + return new DmlReturn("fail", "TIF TYPE ERROR"); + } + if (!FIleChecker.checkTfw(tfwTmpPath)) { + return new DmlReturn("fail", "TFW TYPE ERROR"); + } // 싱크파일목록으로 업로드 경로 확인 List mngFiles = mapSheetMngCoreService.findIdToMapSheetFileList(hstUid); @@ -252,7 +274,9 @@ public class MapSheetMngService { } // 중복제거 확인후 처리상태(DONE)변경 - if (hstUid > 0) mapSheetMngCoreService.updateByHstUidSyncCheckState(hstUid); + if (hstUid > 0) { + mapSheetMngCoreService.updateByHstUidSyncCheckState(hstUid); + } return new DmlReturn("success", fileUids.size() + "개 파일이 삭제되었습니다."); } diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/core/MapSheetMngCoreService.java b/src/main/java/com/kamco/cd/kamcoback/postgres/core/MapSheetMngCoreService.java index 047b5231..e11a7d68 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/core/MapSheetMngCoreService.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/core/MapSheetMngCoreService.java @@ -1,8 +1,10 @@ package com.kamco.cd.kamcoback.postgres.core; import com.kamco.cd.kamcoback.mapsheet.dto.MapSheetMngDto; +import com.kamco.cd.kamcoback.mapsheet.dto.MapSheetMngDto.YearSearchReq; import com.kamco.cd.kamcoback.postgres.entity.MapSheetMngEntity; import com.kamco.cd.kamcoback.postgres.entity.MapSheetMngHstEntity; +import com.kamco.cd.kamcoback.postgres.entity.YearEntity; import com.kamco.cd.kamcoback.postgres.repository.mapsheet.MapSheetMngRepository; import jakarta.persistence.EntityNotFoundException; import jakarta.validation.Valid; @@ -20,6 +22,7 @@ import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Value; import org.springframework.data.domain.Page; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; @Service @RequiredArgsConstructor @@ -40,6 +43,18 @@ public class MapSheetMngCoreService { return mapSheetMngRepository.findMapSheetMngYyyyList(); } + /** + * 영상등록이 가능한 연도리스트 + * + * @param req + * @return + */ + @Transactional(readOnly = true) + public Page getListMapListYYYYWithPaging(YearSearchReq req) { + + return mapSheetMngRepository.getYears(req); + } + public MapSheetMngDto.MngDto findMapSheetMng(int mngYyyy) { return mapSheetMngRepository.findMapSheetMng(mngYyyy); } @@ -146,18 +161,18 @@ public class MapSheetMngCoreService { }) .sum(); - entity.get().setTifSizeBytes(tifSize); - entity.get().setTfwSizeBytes(tfwSize); - entity.get().setTotalSizeBytes(tifSize + tfwSize); + MapSheetMngHstEntity mapSheetMngHst = entity.get(); + + mapSheetMngHst.updateFileInfos(tifSize, tfwSize); // 엔터티 저장 -> 커스텀 업데이트로 변경 mapSheetMngRepository.updateHstFileSizes( entity.get().getHstUid(), tifSize, tfwSize, tifSize + tfwSize); } catch (IOException e) { // 크기 계산 실패 시 0으로 저장 - entity.get().setTifSizeBytes(0L); - entity.get().setTfwSizeBytes(0L); - entity.get().setTotalSizeBytes(0L); + MapSheetMngHstEntity mapSheetMng = entity.get(); + mapSheetMng.updateFileInfos(0L, 0L); + mapSheetMngRepository.updateHstFileSizes(entity.get().getHstUid(), 0L, 0L, 0L); } @@ -254,13 +269,18 @@ public class MapSheetMngCoreService { List filesDto = mapSheetMngRepository.findHstUidToMapSheetFileList(hstUid); for (MapSheetMngDto.MngFilesDto dto : filesDto) { - if (dto.getFileExt().equals("tif")) reqDto.setSyncCheckTifFileName(dto.getFileName()); - else if (dto.getFileExt().equals("tfw")) reqDto.setSyncCheckTfwFileName(dto.getFileName()); + if (dto.getFileExt().equals("tif")) { + reqDto.setSyncCheckTifFileName(dto.getFileName()); + } else if (dto.getFileExt().equals("tfw")) { + reqDto.setSyncCheckTfwFileName(dto.getFileName()); + } reqDto.setFilePath(dto.getFilePath()); } String fileState = "DONE"; - if (filesDto.size() > 2) fileState = "DONE"; + if (filesDto.size() > 2) { + fileState = "DONE"; + } reqDto.setSyncCheckState(fileState); diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MapSheetMngHstEntity.java b/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MapSheetMngHstEntity.java index ad81fbc7..2cf1f359 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MapSheetMngHstEntity.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MapSheetMngHstEntity.java @@ -1,37 +1,92 @@ package com.kamco.cd.kamcoback.postgres.entity; import com.kamco.cd.kamcoback.postgres.CommonDateEntity; -import jakarta.persistence.*; +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.Table; import jakarta.validation.constraints.Size; import java.time.ZonedDateTime; +import lombok.AccessLevel; import lombok.Getter; -import lombok.Setter; +import lombok.NoArgsConstructor; +/** + * This class represents the entity for managing the history of map sheets. It is mapped to the + * database table "tb_map_sheet_mng_hst" and contains various properties related to the 1:5k map + * sheet information, as well as metadata for file synchronization and management. + * + *

This entity: - Includes a primary key (hstUid) for unique identification. - Maintains + * information associated with map sheets such as code, name, scale ratio, and paths. - Tracks + * states, timestamps, and data synchronization details. - Maintains relationships with the + * `MapInkx5kEntity` entity through a many-to-one association. - Provides functionality to update + * file information and sizes (`tifSizeBytes`, `tfwSizeBytes`, and `totalSizeBytes`). + * + *

It extends the `CommonDateEntity` class to include common date management fields, such as + * creation and modification timestamps. + * + *

The `@Getter` annotation generates getter methods for all fields, while the access to setters + * is restricted to enforce controlled modifications. The entity uses `@NoArgsConstructor` with + * `AccessLevel.PROTECTED` to restrict direct instantiation. The `updateFileInfos` method allows + * dynamic updates of specific file information. + * + *

Fields include: - hstUid: Unique identifier for the history record. - mngYyyy: Year associated + * with the management record. - mapInkx5kByCode: Reference to the related `MapInkx5kEntity` object. + * - mapSheetNum: Map sheet number identifying specific map. - mapSheetName: Name of the map sheet. + * - mapSheetCodeSrc: Source code of the map sheet. - scaleRatio: Scale ratio of the map. - + * dataState: State/status of the map sheet data. - dataStateDttm: Timestamp of the data state. - + * useInference: Indicator or metadata for inference usage. - useInferenceDttm: Timestamp for + * inference-related use. - mapSheetPath: Path or location of the map sheet file. - refMapSheetNum: + * Reference to a related map sheet number. - createdUid: User ID of the record creator. - + * updatedUid: User ID of the last updater. - syncState and related fields: Fields to manage + * synchronization states and processes. - tifSizeBytes, tfwSizeBytes, totalSizeBytes: Fields to + * track file size details. - sync file name fields: Stores names of files relevant for + * synchronization and verification. + * + *

This entity is essential for tracking and managing map sheet revisions, status, and usage in a + * system leveraging 1:5k map data. + */ @Getter -@Setter +// entity의 접근제어를 위해 @setter를 사용 x +// @Setter +@NoArgsConstructor(access = AccessLevel.PROTECTED) @Entity +// 영상관리이력 @Table(name = "tb_map_sheet_mng_hst") public class MapSheetMngHstEntity extends CommonDateEntity { + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "hst_uid") - private Long hstUid; + private Long hstUid; // id @Column(name = "mng_yyyy") - private Integer mngYyyy; + private Integer mngYyyy; // 년도 - @Column(name = "map_sheet_code") - private Integer mapSheetCode; + // JPA 연관관계: MapInkx5k 참조 (PK 기반) 소속도엽번호 1:5k + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "map_sheet_code", referencedColumnName = "fid") + private MapInkx5kEntity mapInkx5kByCode; + // TODO 1:5k 관련 정보 추후 제거 필요 @Column(name = "map_sheet_num") - private String mapSheetNum; + private String mapSheetNum; // 도엽번호 @Column(name = "map_sheet_name") private String mapSheetName; + // TODO END + + // 도엽파일이 저장된 경로 @Column(name = "map_sheet_code_src") private Integer mapSheetCodeSrc; + // 도엽비율? @Column(name = "scale_ratio") private Integer scaleRatio; @@ -103,4 +158,13 @@ public class MapSheetMngHstEntity extends CommonDateEntity { @Size(max = 100) @Column(name = "sync_check_tfw_file_name", length = 100) private String syncCheckTfwFileName; + + // 파일정보 업데이트 + public void updateFileInfos(Long tifSizeBytes, Long tfwSizeBytes) { + tifSizeBytes = tifSizeBytes == null ? 0L : tifSizeBytes; + tfwSizeBytes = tfwSizeBytes == null ? 0L : tfwSizeBytes; + this.tifSizeBytes = tifSizeBytes; + this.tfwSizeBytes = tfwSizeBytes; + this.totalSizeBytes = tifSizeBytes + tfwSizeBytes; + } } diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/mapsheet/MapSheetMngRepositoryCustom.java b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/mapsheet/MapSheetMngRepositoryCustom.java index b26508da..4c070e95 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/mapsheet/MapSheetMngRepositoryCustom.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/mapsheet/MapSheetMngRepositoryCustom.java @@ -1,7 +1,9 @@ package com.kamco.cd.kamcoback.postgres.repository.mapsheet; import com.kamco.cd.kamcoback.mapsheet.dto.MapSheetMngDto; +import com.kamco.cd.kamcoback.mapsheet.dto.MapSheetMngDto.YearSearchReq; import com.kamco.cd.kamcoback.postgres.entity.MapSheetMngHstEntity; +import com.kamco.cd.kamcoback.postgres.entity.YearEntity; import jakarta.validation.Valid; import java.util.List; import java.util.Optional; @@ -55,4 +57,6 @@ public interface MapSheetMngRepositoryCustom { MapSheetMngDto.MngFilesDto findIdToMapSheetFile(Long fileUid); void updateHstFileSizes(Long hstUid, long tifSizeBytes, long tfwSizeBytes, long totalSizeBytes); + + Page getYears(YearSearchReq yearSearchReq); } diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/mapsheet/MapSheetMngRepositoryImpl.java b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/mapsheet/MapSheetMngRepositoryImpl.java index add560c9..7e970baa 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/mapsheet/MapSheetMngRepositoryImpl.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/mapsheet/MapSheetMngRepositoryImpl.java @@ -8,7 +8,10 @@ import static com.kamco.cd.kamcoback.postgres.entity.QMapSheetMngHstEntity.mapSh import static com.kamco.cd.kamcoback.postgres.entity.QYearEntity.yearEntity; import com.kamco.cd.kamcoback.mapsheet.dto.MapSheetMngDto; +import com.kamco.cd.kamcoback.mapsheet.dto.MapSheetMngDto.YearSearchReq; import com.kamco.cd.kamcoback.postgres.entity.MapSheetMngHstEntity; +import com.kamco.cd.kamcoback.postgres.entity.QYearEntity; +import com.kamco.cd.kamcoback.postgres.entity.YearEntity; import com.querydsl.core.BooleanBuilder; import com.querydsl.core.types.Projections; import com.querydsl.core.types.dsl.BooleanExpression; @@ -295,23 +298,7 @@ public class MapSheetMngRepositoryImpl extends QuerydslRepositorySupport mapSheetMngHstEntity.syncState.ne("DONE").and(mapSheetMngHstEntity.syncState.ne("NOTYET"))); if (searchReq.getSyncState() != null && !searchReq.getSyncState().isEmpty()) { - /* - if (searchReq.getSyncState().equals("NOTPAIR")) { - whereBuilder.and( - mapSheetMngHstEntity - .syncState - .eq("NOTPAIR") - .or(mapSheetMngHstEntity.syncState.eq("NOFILE"))); - } else if (searchReq.getSyncState().equals("FAULT")) { - whereBuilder.and( - mapSheetMngHstEntity - .syncState - .eq("SIZEERROR") - .or(mapSheetMngHstEntity.syncState.eq("TYPEERROR"))); - } else { - whereBuilder.and(mapSheetMngHstEntity.syncState.eq(searchReq.getSyncState())); - } - */ + whereBuilder.and(mapSheetMngHstEntity.syncState.eq(searchReq.getSyncState())); } @@ -379,8 +366,7 @@ public class MapSheetMngRepositoryImpl extends QuerydslRepositorySupport queryFactory .select(mapSheetMngHstEntity.hstUid.count()) .from(mapSheetMngHstEntity) - .innerJoin(mapInkx5kEntity) - .on(mapSheetMngHstEntity.mapSheetCode.eq(mapInkx5kEntity.fid)) + .innerJoin(mapSheetMngHstEntity.mapInkx5kByCode, mapInkx5kEntity) .leftJoin(mapInkx50kEntity) .on(mapInkx5kEntity.fidK50.eq(mapInkx50kEntity.fid.longValue())) .where(whereBuilder) @@ -737,6 +723,35 @@ public class MapSheetMngRepositoryImpl extends QuerydslRepositorySupport query.executeUpdate(); } + @Override + public Page getYears(YearSearchReq req) { + Pageable pageable = req.toPageable(); + // LISTS + List content = + queryFactory + .selectFrom(yearEntity) + .where(eqYearStatus(yearEntity, req.getStatus())) + .offset(pageable.getOffset()) + .limit(pageable.getPageSize()) + .orderBy(yearEntity.yyyy.asc()) + .fetch(); + // count 쿼리 + Long total = + queryFactory + .select(yearEntity.yyyy.count()) + .from(yearEntity) + .where(eqYearStatus(yearEntity, req.getStatus())) + .fetchOne(); + return new PageImpl<>(content, pageable, total); + } + + private BooleanExpression eqYearStatus(QYearEntity years, String status) { + if (status == null) { + return null; + } + return years.status.eq(status); + } + private NumberExpression rowNum() { return Expressions.numberTemplate( Integer.class, "row_number() over(order by {0} desc)", mapSheetMngHstEntity.createdDate);