From 78d1f4fc9a58c39e19954424878b3ff7bfc0fda3 Mon Sep 17 00:00:00 2001 From: teddy Date: Wed, 24 Dec 2025 09:11:03 +0900 Subject: [PATCH 1/4] =?UTF-8?q?=EB=A9=94=EB=89=B4=20=EC=9E=84=EC=8B=9C=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/RedisAuthorizationManager.java | 2 +- .../cd/kamcoback/menu/MyMenusApiController.java | 8 ++++++++ .../kamco/cd/kamcoback/menu/dto/MenuDto.java | 5 +---- .../kamcoback/postgres/entity/MenuEntity.java | 17 +++++++++++------ .../repository/menu/MenuRepositoryImpl.java | 9 ++------- 5 files changed, 23 insertions(+), 18 deletions(-) create mode 100644 src/main/java/com/kamco/cd/kamcoback/menu/MyMenusApiController.java diff --git a/src/main/java/com/kamco/cd/kamcoback/auth/RedisAuthorizationManager.java b/src/main/java/com/kamco/cd/kamcoback/auth/RedisAuthorizationManager.java index 9fcb3b16..ddbff3e2 100644 --- a/src/main/java/com/kamco/cd/kamcoback/auth/RedisAuthorizationManager.java +++ b/src/main/java/com/kamco/cd/kamcoback/auth/RedisAuthorizationManager.java @@ -86,7 +86,7 @@ public class RedisAuthorizationManager continue; } - String baseUri = menu.getMenuApiUri(); + String baseUri = menu.getMenuUrl(); if (baseUri == null || baseUri.isBlank()) { continue; } diff --git a/src/main/java/com/kamco/cd/kamcoback/menu/MyMenusApiController.java b/src/main/java/com/kamco/cd/kamcoback/menu/MyMenusApiController.java new file mode 100644 index 00000000..2ca41821 --- /dev/null +++ b/src/main/java/com/kamco/cd/kamcoback/menu/MyMenusApiController.java @@ -0,0 +1,8 @@ +package com.kamco.cd.kamcoback.menu; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/api/my/menus") +public class MyMenusApiController {} diff --git a/src/main/java/com/kamco/cd/kamcoback/menu/dto/MenuDto.java b/src/main/java/com/kamco/cd/kamcoback/menu/dto/MenuDto.java index e331b3df..38a49960 100644 --- a/src/main/java/com/kamco/cd/kamcoback/menu/dto/MenuDto.java +++ b/src/main/java/com/kamco/cd/kamcoback/menu/dto/MenuDto.java @@ -45,8 +45,7 @@ public class MenuDto { Long updatedUid, List children, ZonedDateTime createdDttm, - ZonedDateTime updatedDttm, - String menuApiUrl) { + ZonedDateTime updatedDttm) { this.menuUid = menuUid; this.menuNm = menuNm; this.menuUrl = menuUrl; @@ -59,7 +58,6 @@ public class MenuDto { this.children = children; this.createdDttm = createdDttm; this.updatedDttm = updatedDttm; - this.menuApiUrl = menuApiUrl; } } @@ -70,7 +68,6 @@ public class MenuDto { private String menuUid; private String menuNm; private String menuUrl; - private String menuApiUri; private String roles; // "ROLE_A,ROLE_B" } } diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MenuEntity.java b/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MenuEntity.java index 15c98cea..d008e247 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MenuEntity.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MenuEntity.java @@ -2,7 +2,15 @@ package com.kamco.cd.kamcoback.postgres.entity; import com.kamco.cd.kamcoback.menu.dto.MenuDto; import com.kamco.cd.kamcoback.postgres.CommonDateEntity; -import jakarta.persistence.*; +import jakarta.persistence.CascadeType; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToMany; +import jakarta.persistence.Table; import jakarta.validation.constraints.NotNull; import java.util.ArrayList; import java.util.List; @@ -15,6 +23,7 @@ import lombok.NoArgsConstructor; @NoArgsConstructor(access = AccessLevel.PROTECTED) @Table(name = "tb_menu") public class MenuEntity extends CommonDateEntity { + @Id @Column(name = "menu_uid") private String menuUid; @@ -49,9 +58,6 @@ public class MenuEntity extends CommonDateEntity { @OneToMany(mappedBy = "parent", fetch = FetchType.LAZY, cascade = CascadeType.ALL) private List children = new ArrayList<>(); - @Column(name = "menu_api_uri") - private String menuApiUri; - public MenuDto.Basic toDto() { return new MenuDto.Basic( this.menuUid, @@ -65,7 +71,6 @@ public class MenuEntity extends CommonDateEntity { this.updatedUid, this.children.stream().map(MenuEntity::toDto).toList(), this.getCreatedDate(), - this.getModifiedDate(), - this.menuApiUri); + this.getModifiedDate()); } } diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/menu/MenuRepositoryImpl.java b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/menu/MenuRepositoryImpl.java index a995e7d7..db79e0af 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/menu/MenuRepositoryImpl.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/menu/MenuRepositoryImpl.java @@ -72,17 +72,12 @@ public class MenuRepositoryImpl implements MenuRepositoryCustom { queryFactory .select( Projections.constructor( - MenuWithRolesDto.class, - tm.menuUid, - tm.menuNm, - tm.menuUrl, - tm.menuApiUri, - roleAgg)) + MenuWithRolesDto.class, tm.menuUid, tm.menuNm, tm.menuUrl, roleAgg)) .from(tm) .leftJoin(tmm) .on(tmm.menuUid.eq(tm).and(tmm.deleted.isFalse())) .where(tm.deleted.isFalse()) - .groupBy(tm.menuUid, tm.menuNm, tm.menuUrl, tm.menuApiUri) + .groupBy(tm.menuUid, tm.menuNm, tm.menuUrl) .fetch(); return content; } From f85d6c07b762dafd7a0967b0202d5adbd5594afb Mon Sep 17 00:00:00 2001 From: teddy Date: Wed, 24 Dec 2025 11:04:50 +0900 Subject: [PATCH 2/4] =?UTF-8?q?=EB=A9=94=EB=89=B4=20=EC=B6=94=EA=B0=80=20?= =?UTF-8?q?=EB=B0=8F=20spotless=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/MenuAuthorizationManager.java | 101 ++++++++++ .../auth/RedisAuthorizationManager.java | 188 ------------------ .../cd/kamcoback/config/SecurityConfig.java | 2 - .../mapsheet/MapSheetMngApiController.java | 3 +- .../mapsheet/service/MapSheetMngService.java | 14 +- .../cd/kamcoback/menu/MenuApiController.java | 43 ---- .../kamcoback/menu/MyMenuApiController.java | 47 +++++ .../kamcoback/menu/MyMenusApiController.java | 8 - .../cd/kamcoback/menu/dto/MyMenuDto.java | 29 +++ .../kamcoback/menu/service/MenuService.java | 60 ------ .../kamcoback/menu/service/MyMenuService.java | 26 +++ .../postgres/core/MenuCoreService.java | 46 ++++- .../repository/menu/MenuRepositoryCustom.java | 6 +- .../repository/menu/MenuRepositoryImpl.java | 62 +++--- 14 files changed, 285 insertions(+), 350 deletions(-) create mode 100644 src/main/java/com/kamco/cd/kamcoback/auth/MenuAuthorizationManager.java delete mode 100644 src/main/java/com/kamco/cd/kamcoback/auth/RedisAuthorizationManager.java create mode 100644 src/main/java/com/kamco/cd/kamcoback/menu/MyMenuApiController.java delete mode 100644 src/main/java/com/kamco/cd/kamcoback/menu/MyMenusApiController.java create mode 100644 src/main/java/com/kamco/cd/kamcoback/menu/dto/MyMenuDto.java create mode 100644 src/main/java/com/kamco/cd/kamcoback/menu/service/MyMenuService.java diff --git a/src/main/java/com/kamco/cd/kamcoback/auth/MenuAuthorizationManager.java b/src/main/java/com/kamco/cd/kamcoback/auth/MenuAuthorizationManager.java new file mode 100644 index 00000000..0cc3db39 --- /dev/null +++ b/src/main/java/com/kamco/cd/kamcoback/auth/MenuAuthorizationManager.java @@ -0,0 +1,101 @@ +package com.kamco.cd.kamcoback.auth; + +import com.kamco.cd.kamcoback.postgres.entity.MenuEntity; +import com.kamco.cd.kamcoback.postgres.repository.menu.MenuRepository; +import jakarta.servlet.http.HttpServletRequest; +import java.util.List; +import java.util.function.Supplier; +import lombok.RequiredArgsConstructor; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.springframework.security.authorization.AuthorizationDecision; +import org.springframework.security.authorization.AuthorizationManager; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.web.access.intercept.RequestAuthorizationContext; +import org.springframework.stereotype.Component; + +/** + * DB 기반 메뉴 권한 AuthorizationManager + * + *

- Redis 사용 안 함 - ADMIN 예외 없음 (DB 매핑 기준) - 한 계정 = role 1개 - menu_url(prefix) 기반 API 접근 제어 + */ +@Component +@RequiredArgsConstructor +public class MenuAuthorizationManager implements AuthorizationManager { + + private static final Logger log = LogManager.getLogger(MenuAuthorizationManager.class); + + private final MenuRepository menuAuthQueryRepository; + + @Override + public AuthorizationDecision check( + Supplier authenticationSupplier, RequestAuthorizationContext context) { + + HttpServletRequest request = context.getRequest(); + String requestPath = normalizePath(request.getRequestURI()); + + Authentication authentication = authenticationSupplier.get(); + if (authentication == null || !authentication.isAuthenticated()) { + return new AuthorizationDecision(false); + } + + String role = extractSingleRole(authentication); + if (role == null) { + return new AuthorizationDecision(false); + } + + // DB에서 role에 허용된 메뉴 조회 + List allowedMenus = menuAuthQueryRepository.findAllowedMenuUrlsByRole(role); + + if (allowedMenus == null || allowedMenus.isEmpty()) { + return new AuthorizationDecision(false); + } + + // menu_url(prefix) 기반 접근 허용 판단 + for (MenuEntity menu : allowedMenus) { + String baseUri = menu.getMenuUrl(); + if (baseUri == null || baseUri.isBlank()) { + continue; + } + if (matchUri(baseUri, requestPath)) { + return new AuthorizationDecision(true); + } + } + + return new AuthorizationDecision(false); + } + + /* ========================= + * role 추출 + * ========================= */ + private String extractSingleRole(Authentication authentication) { + GrantedAuthority ga = authentication.getAuthorities().stream().findFirst().orElse(null); + + if (ga == null || ga.getAuthority() == null || ga.getAuthority().isBlank()) { + return null; + } + + String auth = ga.getAuthority(); + return auth.startsWith("ROLE_") ? auth.substring(5) : auth; + } + + /* ========================= + * URI prefix 매칭 + * ========================= */ + private boolean matchUri(String baseUri, String requestPath) { + String base = normalizePath(baseUri); + String req = normalizePath(requestPath); + return req.equals(base) || req.startsWith(base + "/"); + } + + /* ========================= + * URI 정규화 + * ========================= */ + private String normalizePath(String path) { + if (path == null || path.isBlank()) { + return "/"; + } + return path.replaceAll("//+", "/"); + } +} diff --git a/src/main/java/com/kamco/cd/kamcoback/auth/RedisAuthorizationManager.java b/src/main/java/com/kamco/cd/kamcoback/auth/RedisAuthorizationManager.java deleted file mode 100644 index ddbff3e2..00000000 --- a/src/main/java/com/kamco/cd/kamcoback/auth/RedisAuthorizationManager.java +++ /dev/null @@ -1,188 +0,0 @@ -package com.kamco.cd.kamcoback.auth; - -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.kamco.cd.kamcoback.common.enums.RoleType; -import com.kamco.cd.kamcoback.menu.dto.MenuDto; -import jakarta.servlet.http.HttpServletRequest; -import java.util.Collections; -import java.util.List; -import java.util.function.Supplier; -import lombok.RequiredArgsConstructor; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.springframework.data.redis.core.StringRedisTemplate; -import org.springframework.security.authorization.AuthorizationDecision; -import org.springframework.security.authorization.AuthorizationManager; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.web.access.intercept.RequestAuthorizationContext; -import org.springframework.stereotype.Component; - -/** redis에 등록된 메뉴별 권한 확인 */ -@Component -@RequiredArgsConstructor -public class RedisAuthorizationManager - implements AuthorizationManager { - - private static final Logger log = LogManager.getLogger(RedisAuthorizationManager.class); - private static final String REDIS_KEY = "auth:api:role"; - - private final StringRedisTemplate redisTemplate; - private final ObjectMapper objectMapper; - - @Override - public AuthorizationDecision check( - Supplier authenticationSupplier, RequestAuthorizationContext context) { - - HttpServletRequest request = context.getRequest(); - String requestPath = normalizePath(request.getRequestURI()); - - Authentication authentication = authenticationSupplier.get(); - if (authentication == null || !authentication.isAuthenticated()) { - return new AuthorizationDecision(false); - } - - // ADMIN 은 무조건 허용 - if (hasAdmin(authentication)) { - return new AuthorizationDecision(true); - } - - // 사용자 role 목록 - List userRoles = extractRoles(authentication); - if (userRoles.isEmpty()) { - return new AuthorizationDecision(false); - } - - // Redis 조회 (1회) - String json = redisTemplate.opsForValue().get(REDIS_KEY); - if (json == null || json.isBlank()) { - return new AuthorizationDecision(false); - } - - // JSON 파싱 (1회) - List menus = parseMenus(json); - if (menus.isEmpty()) { - return new AuthorizationDecision(false); - } - - // role + prefix URI 매칭 - for (String role : userRoles) { - if (isAllowed(menus, role, requestPath)) { - return new AuthorizationDecision(true); - } - } - - return new AuthorizationDecision(false); - } - - /* ========================= - * 핵심 권한 판별 로직 - * ========================= */ - private boolean isAllowed(List menus, String role, String requestPath) { - - for (MenuDto.MenuWithRolesDto menu : menus) { - if (menu == null) { - continue; - } - - String baseUri = menu.getMenuUrl(); - if (baseUri == null || baseUri.isBlank()) { - continue; - } - - // role 포함 여부 - if (!hasRole(menu.getRoles(), role)) { - continue; - } - - // prefix URI 허용 - if (matchUri(baseUri, requestPath)) { - return true; - } - } - return false; - } - - /* ========================= - * URI prefix 매칭 - * ========================= */ - private boolean matchUri(String baseUri, String requestPath) { - String base = normalizePath(baseUri); - String req = normalizePath(requestPath); - - // /api/log/audit → /api/log/audit/** - return req.equals(base) || req.startsWith(base + "/"); - } - - /* ========================= - * role 문자열 처리 - * ========================= */ - private boolean hasRole(String rolesCsv, String targetRole) { - if (rolesCsv == null || rolesCsv.isBlank()) { - return false; - } - if (targetRole == null || targetRole.isBlank()) { - return false; - } - - for (String r : rolesCsv.split(",")) { - if (targetRole.equalsIgnoreCase(r.trim())) { - return true; - } - } - return false; - } - - /* ========================= - * Redis JSON 파싱 - * ========================= */ - private List parseMenus(String json) { - try { - return objectMapper.readValue(json, new TypeReference>() {}); - } catch (Exception e) { - log.warn("Failed to parse redis menu json. key={}", REDIS_KEY, e); - return Collections.emptyList(); - } - } - - /* ========================= - * ADMIN 판별 - * ========================= */ - private boolean hasAdmin(Authentication authentication) { - for (GrantedAuthority ga : authentication.getAuthorities()) { - if (ga == null || ga.getAuthority() == null) { - continue; - } - - String auth = ga.getAuthority(); - String admin = RoleType.ADMIN.getId(); - - if (auth.equals(admin) || auth.equals("ROLE_" + admin)) { - return true; - } - } - return false; - } - - /* ========================= - * ROLE 목록 추출 - * ========================= */ - private List extractRoles(Authentication authentication) { - return authentication.getAuthorities().stream() - .map(GrantedAuthority::getAuthority) - .filter(a -> a != null && !a.isBlank()) - .map(a -> a.startsWith("ROLE_") ? a.substring(5) : a) - .toList(); - } - - /* ========================= - * URI 정규화 - * ========================= */ - private String normalizePath(String path) { - if (path == null || path.isBlank()) { - return "/"; - } - return path.replaceAll("//+", "/"); - } -} diff --git a/src/main/java/com/kamco/cd/kamcoback/config/SecurityConfig.java b/src/main/java/com/kamco/cd/kamcoback/config/SecurityConfig.java index a2be68ad..fe1ab0cf 100644 --- a/src/main/java/com/kamco/cd/kamcoback/config/SecurityConfig.java +++ b/src/main/java/com/kamco/cd/kamcoback/config/SecurityConfig.java @@ -2,7 +2,6 @@ package com.kamco.cd.kamcoback.config; import com.kamco.cd.kamcoback.auth.CustomAuthenticationProvider; import com.kamco.cd.kamcoback.auth.JwtAuthenticationFilter; -import com.kamco.cd.kamcoback.auth.RedisAuthorizationManager; import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.context.annotation.Bean; @@ -29,7 +28,6 @@ public class SecurityConfig { private final JwtAuthenticationFilter jwtAuthenticationFilter; private final CustomAuthenticationProvider customAuthenticationProvider; - private final RedisAuthorizationManager redisAuthorizationManager; @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { diff --git a/src/main/java/com/kamco/cd/kamcoback/mapsheet/MapSheetMngApiController.java b/src/main/java/com/kamco/cd/kamcoback/mapsheet/MapSheetMngApiController.java index f71eb3fb..32c8520f 100644 --- a/src/main/java/com/kamco/cd/kamcoback/mapsheet/MapSheetMngApiController.java +++ b/src/main/java/com/kamco/cd/kamcoback/mapsheet/MapSheetMngApiController.java @@ -177,7 +177,8 @@ public class MapSheetMngApiController { @RequestPart("tif") MultipartFile tifFile, @RequestParam(value = "hstUid", required = false) Long hstUid, @RequestParam(value = "overwrite", required = false) boolean overwrite) { - return ApiResponseDto.createOK(mapSheetMngService.uploadPair(tfwFile, tifFile, hstUid, overwrite)); + return ApiResponseDto.createOK( + mapSheetMngService.uploadPair(tfwFile, tifFile, hstUid, overwrite)); } @Operation(summary = "영상관리 > 파일조회", description = "영상관리 > 파일조회") 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 2518388b..ffa25353 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 @@ -74,7 +74,8 @@ public class MapSheetMngService { } @Transactional - public DmlReturn uploadPair(MultipartFile tfwFile, MultipartFile tifFile, Long hstUid, Boolean overwrite) { + public DmlReturn uploadPair( + MultipartFile tfwFile, MultipartFile tifFile, Long hstUid, Boolean overwrite) { String rootPath = fileConfig.getRootSyncDir(); String tmpPath = fileConfig.getTmpSyncDir(); @@ -126,16 +127,13 @@ public class MapSheetMngService { .filter(dto -> dto.getExtension().toString().equals("tif")) .count(); - if( !overwrite ) { + 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); } diff --git a/src/main/java/com/kamco/cd/kamcoback/menu/MenuApiController.java b/src/main/java/com/kamco/cd/kamcoback/menu/MenuApiController.java index 3d8f2710..72435eda 100644 --- a/src/main/java/com/kamco/cd/kamcoback/menu/MenuApiController.java +++ b/src/main/java/com/kamco/cd/kamcoback/menu/MenuApiController.java @@ -1,7 +1,6 @@ package com.kamco.cd.kamcoback.menu; import com.fasterxml.jackson.databind.ObjectMapper; -import com.kamco.cd.kamcoback.common.utils.UserUtil; import com.kamco.cd.kamcoback.config.api.ApiLogFunction; import com.kamco.cd.kamcoback.config.api.ApiResponseDto; import com.kamco.cd.kamcoback.menu.dto.MenuDto; @@ -11,17 +10,14 @@ import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; -import io.swagger.v3.oas.annotations.tags.Tag; import java.util.LinkedHashMap; import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; -@Tag(name = "메뉴 관리", description = "메뉴 관리 API") @RestController @RequiredArgsConstructor @RequestMapping("/api/menu") @@ -68,43 +64,4 @@ public class MenuApiController { return ApiResponseDto.ok(ApiLogFunction.getUriMenuInfo(result, apiUri)); } - - @Operation(summary = "권한별 메뉴 레디스 저장", description = "권한별 메뉴 레디스 저장") - @ApiResponses( - value = { - @ApiResponse( - responseCode = "201", - description = "등록 성공", - content = - @Content( - mediaType = "application/json", - schema = @Schema(implementation = MenuDto.Basic.class))), - @ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content), - @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) - }) - @PostMapping("/auth") - public ApiResponseDto getFindByRoleRedis() { - menuService.getFindByRoleRedis(); - return ApiResponseDto.createOK("ok"); - } - - @Operation(summary = "권한별 메뉴 조회", description = "로그인 권한별 메뉴 목록") - @ApiResponses( - value = { - @ApiResponse( - responseCode = "200", - description = "조회 성공", - content = - @Content( - mediaType = "application/json", - schema = @Schema(implementation = MenuDto.Basic.class))), - @ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content), - @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) - }) - @GetMapping("/auth") - public ApiResponseDto> getFindAllByRole() { - UserUtil userUtil = new UserUtil(); - String role = userUtil.getRole(); - return ApiResponseDto.ok(menuService.getFindByRole(role)); - } } diff --git a/src/main/java/com/kamco/cd/kamcoback/menu/MyMenuApiController.java b/src/main/java/com/kamco/cd/kamcoback/menu/MyMenuApiController.java new file mode 100644 index 00000000..ade26a80 --- /dev/null +++ b/src/main/java/com/kamco/cd/kamcoback/menu/MyMenuApiController.java @@ -0,0 +1,47 @@ +package com.kamco.cd.kamcoback.menu; + +import com.kamco.cd.kamcoback.common.utils.UserUtil; +import com.kamco.cd.kamcoback.config.api.ApiResponseDto; +import com.kamco.cd.kamcoback.menu.dto.MenuDto; +import com.kamco.cd.kamcoback.menu.dto.MyMenuDto; +import com.kamco.cd.kamcoback.menu.service.MyMenuService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import io.swagger.v3.oas.annotations.tags.Tag; +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@Tag(name = "메뉴 조회", description = "메뉴 조회 API") +@RestController +@RequiredArgsConstructor +@RequestMapping("/api/my/menus") +public class MyMenuApiController { + + private final MyMenuService myMenuService; + + @Operation(summary = "사용자별 메뉴 조회", description = "로그인 사용자별 권한 메뉴 목록") + @ApiResponses( + value = { + @ApiResponse( + responseCode = "200", + description = "조회 성공", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = MenuDto.Basic.class))), + @ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content), + @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) + }) + @GetMapping + public ApiResponseDto> getFindAllByRole() { + UserUtil userUtil = new UserUtil(); + String role = userUtil.getRole(); + return ApiResponseDto.ok(myMenuService.getFindByRole(role)); + } +} diff --git a/src/main/java/com/kamco/cd/kamcoback/menu/MyMenusApiController.java b/src/main/java/com/kamco/cd/kamcoback/menu/MyMenusApiController.java deleted file mode 100644 index 2ca41821..00000000 --- a/src/main/java/com/kamco/cd/kamcoback/menu/MyMenusApiController.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.kamco.cd.kamcoback.menu; - -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -@RestController -@RequestMapping("/api/my/menus") -public class MyMenusApiController {} diff --git a/src/main/java/com/kamco/cd/kamcoback/menu/dto/MyMenuDto.java b/src/main/java/com/kamco/cd/kamcoback/menu/dto/MyMenuDto.java new file mode 100644 index 00000000..16ccda3b --- /dev/null +++ b/src/main/java/com/kamco/cd/kamcoback/menu/dto/MyMenuDto.java @@ -0,0 +1,29 @@ +package com.kamco.cd.kamcoback.menu.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import java.util.ArrayList; +import java.util.List; +import lombok.Getter; +import lombok.NoArgsConstructor; + +public class MyMenuDto { + + @Schema(name = "My Menu Basic", description = "사용자별 권한 메뉴 목록") + @Getter + @NoArgsConstructor + public static class Basic { + + private String id; + private String name; + private String menuUrl; + private Long order; + private List children = new ArrayList<>(); + + public Basic(String menuUid, String menuNm, String menuUrl, Long menuOrder) { + this.id = menuUid; + this.name = menuNm; + this.menuUrl = menuUrl; + this.order = menuOrder; + } + } +} diff --git a/src/main/java/com/kamco/cd/kamcoback/menu/service/MenuService.java b/src/main/java/com/kamco/cd/kamcoback/menu/service/MenuService.java index bee0a81f..bf2db12f 100644 --- a/src/main/java/com/kamco/cd/kamcoback/menu/service/MenuService.java +++ b/src/main/java/com/kamco/cd/kamcoback/menu/service/MenuService.java @@ -1,13 +1,9 @@ package com.kamco.cd.kamcoback.menu.service; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.ObjectMapper; -import com.kamco.cd.kamcoback.common.enums.RoleType; import com.kamco.cd.kamcoback.common.utils.UserUtil; import com.kamco.cd.kamcoback.menu.dto.MenuDto; import com.kamco.cd.kamcoback.postgres.core.MenuCoreService; -import java.util.ArrayList; import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.cache.annotation.Cacheable; @@ -27,60 +23,4 @@ public class MenuService { public List getFindAll() { return menuCoreService.getFindAll(); } - - /** - * 권한별 메뉴 목록 redis 등록 - * - * @return - */ - public void getFindByRoleRedis() { - - for (RoleType role : RoleType.values()) { - List menus = menuCoreService.getFindByRole(role.name()); - - try { - String key = "menu:role:" + role.name(); - String value = objectMapper.writeValueAsString(menus); - redisTemplate.opsForValue().set(key, value); - } catch (JsonProcessingException e) { - throw new RuntimeException(e); - } - } - - List menusWithRoles = menuCoreService.getMenuWithRoles(); - - try { - String key = "auth:api:role"; - String value = objectMapper.writeValueAsString(menusWithRoles); - redisTemplate.opsForValue().set(key, value); - } catch (JsonProcessingException e) { - throw new RuntimeException(e); - } - } - - /** - * 권한별 메뉴 목록 조회 - * - * @param role - * @return - */ - public List getFindByRole(String role) { - String key = "menu:role:" + role; - String json = redisTemplate.opsForValue().get(key); - if (json == null) { - return new ArrayList<>(); - } - - JavaType type = - objectMapper.getTypeFactory().constructCollectionType(List.class, MenuDto.Basic.class); - - List cached; - - try { - cached = objectMapper.readValue(json, type); - } catch (JsonProcessingException e) { - throw new RuntimeException(e); - } - return cached; - } } diff --git a/src/main/java/com/kamco/cd/kamcoback/menu/service/MyMenuService.java b/src/main/java/com/kamco/cd/kamcoback/menu/service/MyMenuService.java new file mode 100644 index 00000000..9adad491 --- /dev/null +++ b/src/main/java/com/kamco/cd/kamcoback/menu/service/MyMenuService.java @@ -0,0 +1,26 @@ +package com.kamco.cd.kamcoback.menu.service; + +import com.kamco.cd.kamcoback.menu.dto.MyMenuDto; +import com.kamco.cd.kamcoback.postgres.core.MenuCoreService; +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@RequiredArgsConstructor +@Transactional(readOnly = true) +public class MyMenuService { + + private final MenuCoreService menuCoreService; + + /** + * 권한별 메뉴 목록 조회 + * + * @param role + * @return + */ + public List getFindByRole(String role) { + return menuCoreService.getFindByRole(role); + } +} diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/core/MenuCoreService.java b/src/main/java/com/kamco/cd/kamcoback/postgres/core/MenuCoreService.java index d01054e0..3e9041fe 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/core/MenuCoreService.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/core/MenuCoreService.java @@ -1,8 +1,10 @@ package com.kamco.cd.kamcoback.postgres.core; import com.kamco.cd.kamcoback.menu.dto.MenuDto; +import com.kamco.cd.kamcoback.menu.dto.MyMenuDto; import com.kamco.cd.kamcoback.postgres.entity.MenuEntity; import com.kamco.cd.kamcoback.postgres.repository.menu.MenuRepository; +import java.util.Comparator; import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -23,16 +25,50 @@ public class MenuCoreService { * @param role * @return */ - public List getFindByRole(String role) { - return menuRepository.getFindByRole(role).stream().map(MenuEntity::toDto).toList(); + public List getFindByRole(String role) { + List entities = menuRepository.getFindByRole(role); + + return entities.stream() + .map( + parent -> { + MyMenuDto.Basic p = + new MyMenuDto.Basic( + parent.getMenuUid(), + parent.getMenuNm(), + parent.getMenuUrl(), + parent.getMenuOrder()); + + parent.getChildren().stream() + .filter( + c -> + Boolean.TRUE.equals(c.getIsUse()) && Boolean.FALSE.equals(c.getDeleted())) + .sorted( + Comparator.comparing( + MenuEntity::getMenuOrder, Comparator.nullsLast(Long::compareTo))) + .map( + c -> + new MyMenuDto.Basic( + c.getMenuUid(), c.getMenuNm(), c.getMenuUrl(), c.getMenuOrder())) + .forEach(childDto -> p.getChildren().add(childDto)); + + return p; + }) + .sorted( + Comparator.comparing(MyMenuDto.Basic::getOrder, Comparator.nullsLast(Long::compareTo))) + .toList(); } /** - * 메뉴별 권한 조회 + * 사용자 role 기준으로 접근 가능한 메뉴 URL 목록 조회 * + * @param role * @return */ - public List getMenuWithRoles() { - return menuRepository.getFindByMenuWithRoles(); + public List findAllowedMenuUrlsByRole(String role) { + return menuRepository.findAllowedMenuUrlsByRole(role).stream() + .map(MenuEntity::getMenuUrl) + .filter(url -> url != null && !url.isBlank()) + .distinct() + .toList(); } } diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/menu/MenuRepositoryCustom.java b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/menu/MenuRepositoryCustom.java index d0f8a9b7..775ff647 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/menu/MenuRepositoryCustom.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/menu/MenuRepositoryCustom.java @@ -1,6 +1,5 @@ package com.kamco.cd.kamcoback.postgres.repository.menu; -import com.kamco.cd.kamcoback.menu.dto.MenuDto.MenuWithRolesDto; import com.kamco.cd.kamcoback.postgres.entity.MenuEntity; import java.util.List; @@ -17,9 +16,10 @@ public interface MenuRepositoryCustom { List getFindByRole(String role); /** - * 메뉴별 권한 조회 + * 사용자 role 기준으로 접근 가능한 메뉴 URL 목록 조회 * + * @param role * @return */ - List getFindByMenuWithRoles(); + List findAllowedMenuUrlsByRole(String role); } diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/menu/MenuRepositoryImpl.java b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/menu/MenuRepositoryImpl.java index db79e0af..62a91213 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/menu/MenuRepositoryImpl.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/menu/MenuRepositoryImpl.java @@ -3,13 +3,8 @@ package com.kamco.cd.kamcoback.postgres.repository.menu; import static com.kamco.cd.kamcoback.postgres.entity.QMenuEntity.menuEntity; import static com.kamco.cd.kamcoback.postgres.entity.QMenuMappEntity.menuMappEntity; -import com.kamco.cd.kamcoback.menu.dto.MenuDto.MenuWithRolesDto; import com.kamco.cd.kamcoback.postgres.entity.MenuEntity; import com.kamco.cd.kamcoback.postgres.entity.QMenuEntity; -import com.kamco.cd.kamcoback.postgres.entity.QMenuMappEntity; -import com.querydsl.core.types.Expression; -import com.querydsl.core.types.Projections; -import com.querydsl.core.types.dsl.Expressions; import com.querydsl.jpa.impl.JPAQueryFactory; import java.util.List; import lombok.RequiredArgsConstructor; @@ -34,12 +29,14 @@ public class MenuRepositoryImpl implements MenuRepositoryCustom { @Override public List getFindByRole(String role) { + QMenuEntity parent = QMenuEntity.menuEntity; QMenuEntity child = new QMenuEntity("child"); + List content = queryFactory - .selectDistinct(menuEntity) - .from(menuEntity) - .leftJoin(menuEntity.children, child) + .selectDistinct(parent) + .from(parent) + .leftJoin(parent.children, child) .fetchJoin() .leftJoin(menuMappEntity) .on( @@ -47,38 +44,39 @@ public class MenuRepositoryImpl implements MenuRepositoryCustom { .roleCode .eq(role) .and(menuMappEntity.deleted.isFalse()) - .and( - menuMappEntity.menuUid.eq(menuEntity).or(menuMappEntity.menuUid.eq(child)))) + .and(menuMappEntity.menuUid.eq(child))) .where( - menuEntity.parent.isNull(), - menuEntity.deleted.isFalse(), - menuEntity.isUse.isTrue(), + parent.parent.isNull(), + parent.deleted.isFalse(), + parent.isUse.isTrue(), menuMappEntity.id.isNotNull()) - .orderBy(menuEntity.menuOrder.asc().nullsLast(), child.menuOrder.asc().nullsLast()) + .orderBy(parent.menuOrder.asc().nullsLast(), child.menuOrder.asc().nullsLast()) .fetch(); return content; } + /** + * 사용자 role 기준으로 접근 가능한 메뉴 URL 목록 조회 + * + * @param role + * @return + */ @Override - public List getFindByMenuWithRoles() { - QMenuEntity tm = menuEntity; - QMenuMappEntity tmm = menuMappEntity; + public List findAllowedMenuUrlsByRole(String role) { - Expression roleAgg = - Expressions.stringTemplate("string_agg({0}, {1})", tmm.roleCode, Expressions.constant(",")); - - List content = - queryFactory - .select( - Projections.constructor( - MenuWithRolesDto.class, tm.menuUid, tm.menuNm, tm.menuUrl, roleAgg)) - .from(tm) - .leftJoin(tmm) - .on(tmm.menuUid.eq(tm).and(tmm.deleted.isFalse())) - .where(tm.deleted.isFalse()) - .groupBy(tm.menuUid, tm.menuNm, tm.menuUrl) - .fetch(); - return content; + return queryFactory + .selectDistinct(menuEntity) + .from(menuMappEntity) + .join(menuMappEntity.menuUid, menuEntity) + .where( + menuMappEntity.roleCode.eq(role), + menuMappEntity.deleted.isFalse(), + menuEntity.deleted.isFalse(), + menuEntity.isUse.isTrue(), + menuEntity.menuUrl.isNotNull(), + menuEntity.menuUrl.isNotEmpty()) + .orderBy(menuEntity.menuOrder.asc().nullsLast()) + .fetch(); } } From 72b8a7c41cc0417bb34a056ae1a5ed52a2afb60c Mon Sep 17 00:00:00 2001 From: "gayoun.park" Date: Wed, 24 Dec 2025 11:17:08 +0900 Subject: [PATCH 3/4] =?UTF-8?q?=EB=AA=A8=EB=8D=B8=EA=B4=80=EB=A6=AC=20?= =?UTF-8?q?=EB=AA=A9=EB=A1=9D,=20=EC=82=AD=EC=A0=9C=20API=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=EB=90=9C=20=EB=B2=84=EC=A0=84=20=EC=BB=A4=EB=B0=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../model/ModelMngApiController.java | 57 ++++---- .../cd/kamcoback/model/dto/ModelMngDto.java | 101 ++++++++------- .../model/service/ModelMngService.java | 13 +- .../postgres/entity/ModelMngEntity.java | 13 +- .../model/ModelMngRepositoryCustom.java | 11 +- .../model/ModelMngRepositoryImpl.java | 122 +++++++++--------- 6 files changed, 174 insertions(+), 143 deletions(-) diff --git a/src/main/java/com/kamco/cd/kamcoback/model/ModelMngApiController.java b/src/main/java/com/kamco/cd/kamcoback/model/ModelMngApiController.java index 7989ce31..a09e897b 100644 --- a/src/main/java/com/kamco/cd/kamcoback/model/ModelMngApiController.java +++ b/src/main/java/com/kamco/cd/kamcoback/model/ModelMngApiController.java @@ -13,7 +13,12 @@ import jakarta.transaction.Transactional; import java.time.LocalDate; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; -import org.springframework.web.bind.annotation.*; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; @Tag(name = "모델 관리", description = "모델 관리 API") @RequiredArgsConstructor @@ -27,42 +32,42 @@ public class ModelMngApiController { @Operation(summary = "모델관리 목록") @GetMapping public ApiResponseDto> findModelMgmtList( - @RequestParam(required = false) LocalDate startDate, - @RequestParam(required = false) LocalDate endDate, - @RequestParam(required = false, defaultValue = "createCompleteDttm") String sortColumn, - @RequestParam(required = false) String modelType, - @RequestParam(required = false) String searchVal, - @RequestParam(defaultValue = "0") int page, - @RequestParam(defaultValue = "20") int size) { + @RequestParam(required = false) LocalDate startDate, + @RequestParam(required = false) LocalDate endDate, + @RequestParam(required = false, defaultValue = "createCompleteDttm") String sortColumn, + @RequestParam(required = false) String modelType, + @RequestParam(required = false) String searchVal, + @RequestParam(defaultValue = "0") int page, + @RequestParam(defaultValue = "20") int size) { ModelMngDto.searchReq searchReq = new ModelMngDto.searchReq(page, size, sortColumn + ",desc"); Page result = - modelMngService.findModelMgmtList(searchReq, startDate, endDate, modelType, searchVal); + modelMngService.findModelMgmtList(searchReq, startDate, endDate, modelType, searchVal); return ApiResponseDto.ok(result); } @Operation(summary = "삭제", description = "모델을 삭제 합니다.") @ApiResponses( - value = { - @ApiResponse( - responseCode = "204", - 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) - }) + value = { + @ApiResponse( + responseCode = "204", + 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) + }) @DeleteMapping("/{modelVer}") public ApiResponseDto removeModel( - @io.swagger.v3.oas.annotations.parameters.RequestBody( - description = "모델 삭제 요청 정보", - required = true) - @PathVariable - String modelVer) { + @io.swagger.v3.oas.annotations.parameters.RequestBody( + description = "모델 삭제 요청 정보", + required = true) + @PathVariable + String modelVer) { return ApiResponseDto.okObject(modelMngService.removeModel(modelVer)); } } diff --git a/src/main/java/com/kamco/cd/kamcoback/model/dto/ModelMngDto.java b/src/main/java/com/kamco/cd/kamcoback/model/dto/ModelMngDto.java index 588e0018..5fb01c3b 100644 --- a/src/main/java/com/kamco/cd/kamcoback/model/dto/ModelMngDto.java +++ b/src/main/java/com/kamco/cd/kamcoback/model/dto/ModelMngDto.java @@ -16,41 +16,70 @@ import org.springframework.data.domain.Sort; public class ModelMngDto { + @CodeExpose + @Getter + @AllArgsConstructor + public enum ModelType implements EnumType { + M1("모델 M1"), + M2("모델 M2"), + M3("모델 M3"); + + private final String desc; + + @Override + public String getId() { + return name(); + } + + @Override + public String getText() { + return desc; + } + } + @Schema(name = "ModelMgmtDto Basic", description = "모델관리 엔티티 기본 정보") @Getter @NoArgsConstructor public static class Basic { + private Long modelUid; private String modelVer; - private String hyperVer; - private String epochVer; - private String dockerFileNm; - @JsonFormatDttm private ZonedDateTime createCompleteDttm; - @JsonFormatDttm private ZonedDateTime recentUseDttm; + @JsonFormatDttm + private ZonedDateTime createCompleteDttm; + @JsonFormatDttm + private ZonedDateTime recentUseDttm; private Boolean deleted; - @JsonFormatDttm private ZonedDateTime createdDttm; + @JsonFormatDttm + private ZonedDateTime createdDttm; private Long createdUid; - @JsonFormatDttm private ZonedDateTime updatedDttm; + @JsonFormatDttm + private ZonedDateTime updatedDttm; private Long updatedUid; + private String modelType; + private String filePath; + private String fileName; + private String memo; + public Basic( - String modelVer, - String hyperVer, - String epochVer, - String dockerFileNm, - ZonedDateTime createCompleteDttm, - ZonedDateTime recentUseDttm, - Boolean deleted, - ZonedDateTime createdDttm, - Long createdUid, - ZonedDateTime updatedDttm, - Long updatedUid) { + Long modelUid, + String modelVer, + ZonedDateTime createCompleteDttm, + ZonedDateTime recentUseDttm, + Boolean deleted, + ZonedDateTime createdDttm, + Long createdUid, + ZonedDateTime updatedDttm, + Long updatedUid, + String modelType, + String filePath, + String fileName, + String memo + ) { + this.modelUid = modelUid; this.modelVer = modelVer; - this.hyperVer = hyperVer; - this.epochVer = epochVer; - this.dockerFileNm = dockerFileNm; this.createCompleteDttm = createCompleteDttm; this.recentUseDttm = recentUseDttm; this.deleted = deleted; @@ -58,6 +87,10 @@ public class ModelMngDto { this.createdUid = createdUid; this.updatedDttm = updatedDttm; this.updatedUid = updatedUid; + this.modelType = modelType; + this.filePath = filePath; + this.fileName = fileName; + this.memo = memo; } } @@ -67,17 +100,18 @@ public class ModelMngDto { @NoArgsConstructor @AllArgsConstructor public static class ModelList { + private Integer rowNum; private String modelVer; private String fileName; private String modelType; private String createCompleteDttm; - private String recentUseDttm; private BigDecimal f1Score; private BigDecimal precision; private BigDecimal recall; private BigDecimal accuracy; private BigDecimal iou; + private String memo; private Boolean deleted; } @@ -112,31 +146,10 @@ public class ModelMngDto { String[] sortParams = sort.split(","); String property = sortParams[0]; Sort.Direction direction = - sortParams.length > 1 ? Sort.Direction.fromString(sortParams[1]) : Sort.Direction.ASC; + 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); } } - - @CodeExpose - @Getter - @AllArgsConstructor - public enum ModelType implements EnumType { - M1("모델 M1"), - M2("모델 M2"), - M3("모델 M3"); - - private final String desc; - - @Override - public String getId() { - return name(); - } - - @Override - public String getText() { - return desc; - } - } } diff --git a/src/main/java/com/kamco/cd/kamcoback/model/service/ModelMngService.java b/src/main/java/com/kamco/cd/kamcoback/model/service/ModelMngService.java index 02c7e518..02d8d6ca 100644 --- a/src/main/java/com/kamco/cd/kamcoback/model/service/ModelMngService.java +++ b/src/main/java/com/kamco/cd/kamcoback/model/service/ModelMngService.java @@ -15,16 +15,17 @@ public class ModelMngService { private final ModelMngCoreService modelMngCoreService; public Page findModelMgmtList( - ModelMngDto.searchReq searchReq, - LocalDate startDate, - LocalDate endDate, - String modelType, - String searchVal) { + ModelMngDto.searchReq searchReq, + LocalDate startDate, + LocalDate endDate, + String modelType, + String searchVal) { return modelMngCoreService.findModelMgmtList( - searchReq, startDate, endDate, modelType, searchVal); + searchReq, startDate, endDate, modelType, searchVal); } public ApiResponseDto.ResponseObj removeModel(String modelVer) { return modelMngCoreService.removeModel(modelVer); } + } diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/entity/ModelMngEntity.java b/src/main/java/com/kamco/cd/kamcoback/postgres/entity/ModelMngEntity.java index 9e40a9d9..2e423cee 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/entity/ModelMngEntity.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/entity/ModelMngEntity.java @@ -1,7 +1,12 @@ 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.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.Table; import java.time.ZonedDateTime; import lombok.Getter; import lombok.Setter; @@ -11,6 +16,7 @@ import lombok.Setter; @Entity @Table(name = "tb_model_mng") public class ModelMngEntity extends CommonDateEntity { + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "model_uid") @@ -21,7 +27,7 @@ public class ModelMngEntity extends CommonDateEntity { @Column(name = "create_complete_dttm") private ZonedDateTime createCompleteDttm; - + @Column(name = "recent_use_dttm") private ZonedDateTime recentUseDttm; @@ -43,6 +49,9 @@ public class ModelMngEntity extends CommonDateEntity { @Column(name = "file_name") private String fileName; + @Column(name = "memo") + private String memo; + public void deleted() { this.deleted = true; } diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/model/ModelMngRepositoryCustom.java b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/model/ModelMngRepositoryCustom.java index 5d34fdee..4f89d0b8 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/model/ModelMngRepositoryCustom.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/model/ModelMngRepositoryCustom.java @@ -9,11 +9,12 @@ import org.springframework.data.domain.Page; public interface ModelMngRepositoryCustom { Page findModelMgmtList( - ModelMngDto.searchReq searchReq, - LocalDate startDate, - LocalDate endDate, - String modelType, - String searchVal); + ModelMngDto.searchReq searchReq, + LocalDate startDate, + LocalDate endDate, + String modelType, + String searchVal); Optional findByModelUid(String modelVer); + } diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/model/ModelMngRepositoryImpl.java b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/model/ModelMngRepositoryImpl.java index c9056fe7..0ab11cf3 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/model/ModelMngRepositoryImpl.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/model/ModelMngRepositoryImpl.java @@ -9,7 +9,10 @@ import com.kamco.cd.kamcoback.postgres.entity.ModelMngEntity; import com.querydsl.core.BooleanBuilder; import com.querydsl.core.types.Expression; import com.querydsl.core.types.Projections; -import com.querydsl.core.types.dsl.*; +import com.querydsl.core.types.dsl.BooleanExpression; +import com.querydsl.core.types.dsl.Expressions; +import com.querydsl.core.types.dsl.NumberPath; +import com.querydsl.core.types.dsl.StringExpression; import com.querydsl.jpa.impl.JPAQueryFactory; import java.math.BigDecimal; import java.time.LocalDate; @@ -26,7 +29,7 @@ import org.springframework.data.domain.Sort; import org.springframework.data.jpa.repository.support.QuerydslRepositorySupport; public class ModelMngRepositoryImpl extends QuerydslRepositorySupport - implements ModelMngRepositoryCustom { + implements ModelMngRepositoryCustom { private final JPAQueryFactory queryFactory; private final StringExpression NULL_STRING = Expressions.stringTemplate("cast(null as text)"); @@ -38,19 +41,19 @@ public class ModelMngRepositoryImpl extends QuerydslRepositorySupport @Override public Page findModelMgmtList( - ModelMngDto.searchReq searchReq, - LocalDate startDate, - LocalDate endDate, - String modelType, - String searchVal) { + ModelMngDto.searchReq searchReq, + LocalDate startDate, + LocalDate endDate, + String modelType, + String searchVal) { Pageable pageable = searchReq.toPageable(); Sort sort = pageable.getSort(); String property = "createCompleteDttm"; // 기본으로 생성완료일 기준 Map> sortColumnMap = - Map.of( - "createCompleteDttm", modelMngEntity.createCompleteDttm, - "recentUseDttm", modelMngEntity.recentUseDttm); + Map.of( + "createCompleteDttm", modelMngEntity.createCompleteDttm, + "recentUseDttm", modelMngEntity.recentUseDttm); if (sort.isSorted()) { Sort.Order order = sort.iterator().next(); @@ -60,47 +63,46 @@ public class ModelMngRepositoryImpl extends QuerydslRepositorySupport Expression sortColumn = sortColumnMap.get(property); List foundContent = - queryFactory - .select( - Projections.constructor( - ModelMngDto.ModelList.class, - Expressions.numberTemplate( - Integer.class, "row_number() over(order by {0} desc)", sortColumn), - modelMngEntity.modelVer, - modelMngEntity.fileName, - modelMngEntity.modelType, - Expressions.stringTemplate( - "to_char({0}, 'YYYY-MM-DD')", modelMngEntity.createCompleteDttm), - Expressions.stringTemplate( - "to_char({0}, 'YYYY-MM-DD')", modelMngEntity.recentUseDttm), - roundNumericToPercent(modelResultMetricEntity.f1Score), - roundNumericToPercent(modelResultMetricEntity.precision), - roundNumericToPercent(modelResultMetricEntity.recall), - roundNumericToPercent(modelResultMetricEntity.loss), - roundNumericToPercent(modelResultMetricEntity.iou), - modelMngEntity.deleted)) - .from(modelMngEntity) - .innerJoin(modelResultMetricEntity) - .on(modelMngEntity.modelUid.eq(modelResultMetricEntity.modelUid)) - .where( - eventEndedAtBetween(startDate, endDate, property), - searchModelVersion(modelType, searchVal), - modelMngEntity.deleted.isFalse().or(modelMngEntity.deleted.isNull())) - .offset(pageable.getOffset()) - .limit(pageable.getPageSize()) - .orderBy( - QuerydslOrderUtil.getOrderSpecifiers( - pageable, ModelMngEntity.class, "modelMngEntity")) - .fetch(); + queryFactory + .select( + Projections.constructor( + ModelMngDto.ModelList.class, + Expressions.numberTemplate( + Integer.class, "row_number() over(order by {0} desc)", sortColumn), + modelMngEntity.modelVer, + modelMngEntity.fileName, + modelMngEntity.modelType, + Expressions.stringTemplate( + "to_char({0}, 'YYYY-MM-DD')", modelMngEntity.createCompleteDttm), + roundNumericToPercent(modelResultMetricEntity.f1Score), + roundNumericToPercent(modelResultMetricEntity.precision), + roundNumericToPercent(modelResultMetricEntity.recall), + roundNumericToPercent(modelResultMetricEntity.loss), + roundNumericToPercent(modelResultMetricEntity.iou), + modelMngEntity.memo, + modelMngEntity.deleted)) + .from(modelMngEntity) + .innerJoin(modelResultMetricEntity) + .on(modelMngEntity.modelUid.eq(modelResultMetricEntity.modelUid)) + .where( + eventEndedAtBetween(startDate, endDate, property), + searchModelVersion(modelType, searchVal), + modelMngEntity.deleted.isFalse().or(modelMngEntity.deleted.isNull())) + .offset(pageable.getOffset()) + .limit(pageable.getPageSize()) + .orderBy( + QuerydslOrderUtil.getOrderSpecifiers( + pageable, ModelMngEntity.class, "modelMngEntity")) + .fetch(); Long countQuery = - queryFactory - .select(modelMngEntity.modelUid.count()) - .from(modelMngEntity) - .where( - eventEndedAtBetween(startDate, endDate, property), - searchModelVersion(modelType, searchVal)) - .fetchOne(); + queryFactory + .select(modelMngEntity.modelUid.count()) + .from(modelMngEntity) + .where( + eventEndedAtBetween(startDate, endDate, property), + searchModelVersion(modelType, searchVal)) + .fetchOne(); return new PageImpl<>(foundContent, pageable, countQuery); } @@ -108,14 +110,14 @@ public class ModelMngRepositoryImpl extends QuerydslRepositorySupport @Override public Optional findByModelUid(String modelVer) { return Optional.ofNullable( - queryFactory - .selectFrom(modelMngEntity) - .where(modelMngEntity.modelVer.eq(modelVer)) - .fetchOne()); + queryFactory + .selectFrom(modelMngEntity) + .where(modelMngEntity.modelVer.eq(modelVer)) + .fetchOne()); } private BooleanExpression eventEndedAtBetween( - LocalDate startDate, LocalDate endDate, String sortColumn) { + LocalDate startDate, LocalDate endDate, String sortColumn) { if (Objects.isNull(startDate) || Objects.isNull(endDate)) { return null; } @@ -125,14 +127,14 @@ public class ModelMngRepositoryImpl extends QuerydslRepositorySupport if (sortColumn.equals("createCompleteDttm")) { return modelMngEntity - .createCompleteDttm - .goe(startDateTime.atZone(zone)) - .and(modelMngEntity.createCompleteDttm.lt(endDateTime.atZone(zone))); + .createCompleteDttm + .goe(startDateTime.atZone(zone)) + .and(modelMngEntity.createCompleteDttm.lt(endDateTime.atZone(zone))); } else { return modelMngEntity - .recentUseDttm - .goe(startDateTime.atZone(zone)) - .and(modelMngEntity.recentUseDttm.lt(endDateTime.atZone(zone))); + .recentUseDttm + .goe(startDateTime.atZone(zone)) + .and(modelMngEntity.recentUseDttm.lt(endDateTime.atZone(zone))); } } From b91c0dde095804ed64cda7f9a6e4aec7e864c224 Mon Sep 17 00:00:00 2001 From: "gayoun.park" Date: Wed, 24 Dec 2025 11:17:53 +0900 Subject: [PATCH 4/4] spotless --- .../model/ModelMngApiController.java | 50 ++++---- .../cd/kamcoback/model/dto/ModelMngDto.java | 41 +++---- .../model/service/ModelMngService.java | 13 +- .../postgres/entity/ModelMngEntity.java | 2 +- .../model/ModelMngRepositoryCustom.java | 11 +- .../model/ModelMngRepositoryImpl.java | 116 +++++++++--------- 6 files changed, 113 insertions(+), 120 deletions(-) diff --git a/src/main/java/com/kamco/cd/kamcoback/model/ModelMngApiController.java b/src/main/java/com/kamco/cd/kamcoback/model/ModelMngApiController.java index a09e897b..802a24e1 100644 --- a/src/main/java/com/kamco/cd/kamcoback/model/ModelMngApiController.java +++ b/src/main/java/com/kamco/cd/kamcoback/model/ModelMngApiController.java @@ -32,42 +32,42 @@ public class ModelMngApiController { @Operation(summary = "모델관리 목록") @GetMapping public ApiResponseDto> findModelMgmtList( - @RequestParam(required = false) LocalDate startDate, - @RequestParam(required = false) LocalDate endDate, - @RequestParam(required = false, defaultValue = "createCompleteDttm") String sortColumn, - @RequestParam(required = false) String modelType, - @RequestParam(required = false) String searchVal, - @RequestParam(defaultValue = "0") int page, - @RequestParam(defaultValue = "20") int size) { + @RequestParam(required = false) LocalDate startDate, + @RequestParam(required = false) LocalDate endDate, + @RequestParam(required = false, defaultValue = "createCompleteDttm") String sortColumn, + @RequestParam(required = false) String modelType, + @RequestParam(required = false) String searchVal, + @RequestParam(defaultValue = "0") int page, + @RequestParam(defaultValue = "20") int size) { ModelMngDto.searchReq searchReq = new ModelMngDto.searchReq(page, size, sortColumn + ",desc"); Page result = - modelMngService.findModelMgmtList(searchReq, startDate, endDate, modelType, searchVal); + modelMngService.findModelMgmtList(searchReq, startDate, endDate, modelType, searchVal); return ApiResponseDto.ok(result); } @Operation(summary = "삭제", description = "모델을 삭제 합니다.") @ApiResponses( - value = { - @ApiResponse( - responseCode = "204", - 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) - }) + value = { + @ApiResponse( + responseCode = "204", + 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) + }) @DeleteMapping("/{modelVer}") public ApiResponseDto removeModel( - @io.swagger.v3.oas.annotations.parameters.RequestBody( - description = "모델 삭제 요청 정보", - required = true) - @PathVariable - String modelVer) { + @io.swagger.v3.oas.annotations.parameters.RequestBody( + description = "모델 삭제 요청 정보", + required = true) + @PathVariable + String modelVer) { return ApiResponseDto.okObject(modelMngService.removeModel(modelVer)); } } diff --git a/src/main/java/com/kamco/cd/kamcoback/model/dto/ModelMngDto.java b/src/main/java/com/kamco/cd/kamcoback/model/dto/ModelMngDto.java index 5fb01c3b..ea9da363 100644 --- a/src/main/java/com/kamco/cd/kamcoback/model/dto/ModelMngDto.java +++ b/src/main/java/com/kamco/cd/kamcoback/model/dto/ModelMngDto.java @@ -45,17 +45,13 @@ public class ModelMngDto { private Long modelUid; private String modelVer; - @JsonFormatDttm - private ZonedDateTime createCompleteDttm; - @JsonFormatDttm - private ZonedDateTime recentUseDttm; + @JsonFormatDttm private ZonedDateTime createCompleteDttm; + @JsonFormatDttm private ZonedDateTime recentUseDttm; private Boolean deleted; - @JsonFormatDttm - private ZonedDateTime createdDttm; + @JsonFormatDttm private ZonedDateTime createdDttm; private Long createdUid; - @JsonFormatDttm - private ZonedDateTime updatedDttm; + @JsonFormatDttm private ZonedDateTime updatedDttm; private Long updatedUid; private String modelType; @@ -64,20 +60,19 @@ public class ModelMngDto { private String memo; public Basic( - Long modelUid, - String modelVer, - ZonedDateTime createCompleteDttm, - ZonedDateTime recentUseDttm, - Boolean deleted, - ZonedDateTime createdDttm, - Long createdUid, - ZonedDateTime updatedDttm, - Long updatedUid, - String modelType, - String filePath, - String fileName, - String memo - ) { + Long modelUid, + String modelVer, + ZonedDateTime createCompleteDttm, + ZonedDateTime recentUseDttm, + Boolean deleted, + ZonedDateTime createdDttm, + Long createdUid, + ZonedDateTime updatedDttm, + Long updatedUid, + String modelType, + String filePath, + String fileName, + String memo) { this.modelUid = modelUid; this.modelVer = modelVer; this.createCompleteDttm = createCompleteDttm; @@ -146,7 +141,7 @@ public class ModelMngDto { String[] sortParams = sort.split(","); String property = sortParams[0]; Sort.Direction direction = - sortParams.length > 1 ? Sort.Direction.fromString(sortParams[1]) : Sort.Direction.ASC; + 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/model/service/ModelMngService.java b/src/main/java/com/kamco/cd/kamcoback/model/service/ModelMngService.java index 02d8d6ca..02c7e518 100644 --- a/src/main/java/com/kamco/cd/kamcoback/model/service/ModelMngService.java +++ b/src/main/java/com/kamco/cd/kamcoback/model/service/ModelMngService.java @@ -15,17 +15,16 @@ public class ModelMngService { private final ModelMngCoreService modelMngCoreService; public Page findModelMgmtList( - ModelMngDto.searchReq searchReq, - LocalDate startDate, - LocalDate endDate, - String modelType, - String searchVal) { + ModelMngDto.searchReq searchReq, + LocalDate startDate, + LocalDate endDate, + String modelType, + String searchVal) { return modelMngCoreService.findModelMgmtList( - searchReq, startDate, endDate, modelType, searchVal); + searchReq, startDate, endDate, modelType, searchVal); } public ApiResponseDto.ResponseObj removeModel(String modelVer) { return modelMngCoreService.removeModel(modelVer); } - } diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/entity/ModelMngEntity.java b/src/main/java/com/kamco/cd/kamcoback/postgres/entity/ModelMngEntity.java index 2e423cee..9c06015f 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/entity/ModelMngEntity.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/entity/ModelMngEntity.java @@ -27,7 +27,7 @@ public class ModelMngEntity extends CommonDateEntity { @Column(name = "create_complete_dttm") private ZonedDateTime createCompleteDttm; - + @Column(name = "recent_use_dttm") private ZonedDateTime recentUseDttm; diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/model/ModelMngRepositoryCustom.java b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/model/ModelMngRepositoryCustom.java index 4f89d0b8..5d34fdee 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/model/ModelMngRepositoryCustom.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/model/ModelMngRepositoryCustom.java @@ -9,12 +9,11 @@ import org.springframework.data.domain.Page; public interface ModelMngRepositoryCustom { Page findModelMgmtList( - ModelMngDto.searchReq searchReq, - LocalDate startDate, - LocalDate endDate, - String modelType, - String searchVal); + ModelMngDto.searchReq searchReq, + LocalDate startDate, + LocalDate endDate, + String modelType, + String searchVal); Optional findByModelUid(String modelVer); - } diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/model/ModelMngRepositoryImpl.java b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/model/ModelMngRepositoryImpl.java index 0ab11cf3..18290f45 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/model/ModelMngRepositoryImpl.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/model/ModelMngRepositoryImpl.java @@ -29,7 +29,7 @@ import org.springframework.data.domain.Sort; import org.springframework.data.jpa.repository.support.QuerydslRepositorySupport; public class ModelMngRepositoryImpl extends QuerydslRepositorySupport - implements ModelMngRepositoryCustom { + implements ModelMngRepositoryCustom { private final JPAQueryFactory queryFactory; private final StringExpression NULL_STRING = Expressions.stringTemplate("cast(null as text)"); @@ -41,19 +41,19 @@ public class ModelMngRepositoryImpl extends QuerydslRepositorySupport @Override public Page findModelMgmtList( - ModelMngDto.searchReq searchReq, - LocalDate startDate, - LocalDate endDate, - String modelType, - String searchVal) { + ModelMngDto.searchReq searchReq, + LocalDate startDate, + LocalDate endDate, + String modelType, + String searchVal) { Pageable pageable = searchReq.toPageable(); Sort sort = pageable.getSort(); String property = "createCompleteDttm"; // 기본으로 생성완료일 기준 Map> sortColumnMap = - Map.of( - "createCompleteDttm", modelMngEntity.createCompleteDttm, - "recentUseDttm", modelMngEntity.recentUseDttm); + Map.of( + "createCompleteDttm", modelMngEntity.createCompleteDttm, + "recentUseDttm", modelMngEntity.recentUseDttm); if (sort.isSorted()) { Sort.Order order = sort.iterator().next(); @@ -63,46 +63,46 @@ public class ModelMngRepositoryImpl extends QuerydslRepositorySupport Expression sortColumn = sortColumnMap.get(property); List foundContent = - queryFactory - .select( - Projections.constructor( - ModelMngDto.ModelList.class, - Expressions.numberTemplate( - Integer.class, "row_number() over(order by {0} desc)", sortColumn), - modelMngEntity.modelVer, - modelMngEntity.fileName, - modelMngEntity.modelType, - Expressions.stringTemplate( - "to_char({0}, 'YYYY-MM-DD')", modelMngEntity.createCompleteDttm), - roundNumericToPercent(modelResultMetricEntity.f1Score), - roundNumericToPercent(modelResultMetricEntity.precision), - roundNumericToPercent(modelResultMetricEntity.recall), - roundNumericToPercent(modelResultMetricEntity.loss), - roundNumericToPercent(modelResultMetricEntity.iou), - modelMngEntity.memo, - modelMngEntity.deleted)) - .from(modelMngEntity) - .innerJoin(modelResultMetricEntity) - .on(modelMngEntity.modelUid.eq(modelResultMetricEntity.modelUid)) - .where( - eventEndedAtBetween(startDate, endDate, property), - searchModelVersion(modelType, searchVal), - modelMngEntity.deleted.isFalse().or(modelMngEntity.deleted.isNull())) - .offset(pageable.getOffset()) - .limit(pageable.getPageSize()) - .orderBy( - QuerydslOrderUtil.getOrderSpecifiers( - pageable, ModelMngEntity.class, "modelMngEntity")) - .fetch(); + queryFactory + .select( + Projections.constructor( + ModelMngDto.ModelList.class, + Expressions.numberTemplate( + Integer.class, "row_number() over(order by {0} desc)", sortColumn), + modelMngEntity.modelVer, + modelMngEntity.fileName, + modelMngEntity.modelType, + Expressions.stringTemplate( + "to_char({0}, 'YYYY-MM-DD')", modelMngEntity.createCompleteDttm), + roundNumericToPercent(modelResultMetricEntity.f1Score), + roundNumericToPercent(modelResultMetricEntity.precision), + roundNumericToPercent(modelResultMetricEntity.recall), + roundNumericToPercent(modelResultMetricEntity.loss), + roundNumericToPercent(modelResultMetricEntity.iou), + modelMngEntity.memo, + modelMngEntity.deleted)) + .from(modelMngEntity) + .innerJoin(modelResultMetricEntity) + .on(modelMngEntity.modelUid.eq(modelResultMetricEntity.modelUid)) + .where( + eventEndedAtBetween(startDate, endDate, property), + searchModelVersion(modelType, searchVal), + modelMngEntity.deleted.isFalse().or(modelMngEntity.deleted.isNull())) + .offset(pageable.getOffset()) + .limit(pageable.getPageSize()) + .orderBy( + QuerydslOrderUtil.getOrderSpecifiers( + pageable, ModelMngEntity.class, "modelMngEntity")) + .fetch(); Long countQuery = - queryFactory - .select(modelMngEntity.modelUid.count()) - .from(modelMngEntity) - .where( - eventEndedAtBetween(startDate, endDate, property), - searchModelVersion(modelType, searchVal)) - .fetchOne(); + queryFactory + .select(modelMngEntity.modelUid.count()) + .from(modelMngEntity) + .where( + eventEndedAtBetween(startDate, endDate, property), + searchModelVersion(modelType, searchVal)) + .fetchOne(); return new PageImpl<>(foundContent, pageable, countQuery); } @@ -110,14 +110,14 @@ public class ModelMngRepositoryImpl extends QuerydslRepositorySupport @Override public Optional findByModelUid(String modelVer) { return Optional.ofNullable( - queryFactory - .selectFrom(modelMngEntity) - .where(modelMngEntity.modelVer.eq(modelVer)) - .fetchOne()); + queryFactory + .selectFrom(modelMngEntity) + .where(modelMngEntity.modelVer.eq(modelVer)) + .fetchOne()); } private BooleanExpression eventEndedAtBetween( - LocalDate startDate, LocalDate endDate, String sortColumn) { + LocalDate startDate, LocalDate endDate, String sortColumn) { if (Objects.isNull(startDate) || Objects.isNull(endDate)) { return null; } @@ -127,14 +127,14 @@ public class ModelMngRepositoryImpl extends QuerydslRepositorySupport if (sortColumn.equals("createCompleteDttm")) { return modelMngEntity - .createCompleteDttm - .goe(startDateTime.atZone(zone)) - .and(modelMngEntity.createCompleteDttm.lt(endDateTime.atZone(zone))); + .createCompleteDttm + .goe(startDateTime.atZone(zone)) + .and(modelMngEntity.createCompleteDttm.lt(endDateTime.atZone(zone))); } else { return modelMngEntity - .recentUseDttm - .goe(startDateTime.atZone(zone)) - .and(modelMngEntity.recentUseDttm.lt(endDateTime.atZone(zone))); + .recentUseDttm + .goe(startDateTime.atZone(zone)) + .and(modelMngEntity.recentUseDttm.lt(endDateTime.atZone(zone))); } }