From 4e22683ddb7971b99d2cffbeef22022645a797d7 Mon Sep 17 00:00:00 2001 From: eastargh Date: Thu, 17 Sep 2026 18:03:04 +0900 Subject: [PATCH] =?UTF-8?q?api=5Fstatus=5Fhist=20=EC=A1=B0=ED=9A=8C=20?= =?UTF-8?q?=ED=99=94=EB=A9=B4=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../jsp/common/scheduler/schedulerMan.jsp | 2 +- .../apim/apistatus/hist/apiStatusHistMan.jsp | 194 ++++++++++++++++++ .../onl/djb/apistatus/hist/ApiStatusHist.java | 61 ++++++ .../hist/ApiStatusHistManController.java | 41 ++++ .../hist/ApiStatusHistManService.java | 75 +++++++ .../hist/ApiStatusHistRepository.java | 10 + .../djb/apistatus/hist/ApiStatusHistUI.java | 22 ++ .../apistatus/hist/ApiStatusHistUISearch.java | 23 +++ 8 files changed, 427 insertions(+), 1 deletion(-) create mode 100644 WebContent/jsp/onl/apim/apistatus/hist/apiStatusHistMan.jsp create mode 100644 src/main/java/com/eactive/eai/rms/data/entity/onl/djb/apistatus/hist/ApiStatusHist.java create mode 100644 src/main/java/com/eactive/eai/rms/ext/djb/apistatus/hist/ApiStatusHistManController.java create mode 100644 src/main/java/com/eactive/eai/rms/ext/djb/apistatus/hist/ApiStatusHistManService.java create mode 100644 src/main/java/com/eactive/eai/rms/ext/djb/apistatus/hist/ApiStatusHistRepository.java create mode 100644 src/main/java/com/eactive/eai/rms/ext/djb/apistatus/hist/ApiStatusHistUI.java create mode 100644 src/main/java/com/eactive/eai/rms/ext/djb/apistatus/hist/ApiStatusHistUISearch.java diff --git a/WebContent/jsp/common/scheduler/schedulerMan.jsp b/WebContent/jsp/common/scheduler/schedulerMan.jsp index 92d45c3..dced78b 100644 --- a/WebContent/jsp/common/scheduler/schedulerMan.jsp +++ b/WebContent/jsp/common/scheduler/schedulerMan.jsp @@ -31,7 +31,7 @@ function init(){ new makeOptions("CODE","NAME").setObj($("select[name=searchJobInst]")).setNoValueInclude(true).setNoValue("", "<%= localeMessage.getString("combo.all")%>").setData(json.instanceList).rendering(); - $("select[name=searchJobUseYn]").val("Y"); + //$("select[name=searchJobUseYn]").val("Y"); putSelectFromParam(); diff --git a/WebContent/jsp/onl/apim/apistatus/hist/apiStatusHistMan.jsp b/WebContent/jsp/onl/apim/apistatus/hist/apiStatusHistMan.jsp new file mode 100644 index 0000000..d00b5ba --- /dev/null +++ b/WebContent/jsp/onl/apim/apistatus/hist/apiStatusHistMan.jsp @@ -0,0 +1,194 @@ +<%@ page language="java" contentType="text/html; charset=utf-8" %> +<%@ page import="java.io.*" %> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib uri="http://www.springframework.org/tags" prefix="spring" %> +<%@ include file="/jsp/common/include/localemessage.jsp" %> +<% + response.setHeader("Pragma", "No-cache"); + response.setHeader("Cache-Control", "no-cache"); + response.setHeader("Expires", "0"); +%> + + + + + + + + + + +
+ +
+
+ +
+
API 상태 변경 히스토리API 장애/지연/점검 상태 변경 이력을 조회합니다.
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
API ID변경상태 +
+ +
+
Job명
인스턴스명등록기간 + + ~ + + + +
+
+
+
+
+
+ + diff --git a/src/main/java/com/eactive/eai/rms/data/entity/onl/djb/apistatus/hist/ApiStatusHist.java b/src/main/java/com/eactive/eai/rms/data/entity/onl/djb/apistatus/hist/ApiStatusHist.java new file mode 100644 index 0000000..73dfe04 --- /dev/null +++ b/src/main/java/com/eactive/eai/rms/data/entity/onl/djb/apistatus/hist/ApiStatusHist.java @@ -0,0 +1,61 @@ +package com.eactive.eai.rms.data.entity.onl.djb.apistatus.hist; + +import java.time.LocalDateTime; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.SequenceGenerator; +import javax.persistence.Table; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +/** + * API 상태 변경 히스토리(API_STATUS_HIST) - 조회 전용 엔티티. + * + *

{@code ApiStatusService.updateApiStatus()}에서 상태 전이 CAS 선점에 성공한 건에 대해 + * {@code ApiStatusRepository.insertHistory()}(native INSERT)로 1건씩 적재된다. 이 엔티티는 + * 그 적재 결과를 조회하는 용도로만 쓴다.

+ */ +@Entity +@Table(name = "API_STATUS_HIST") +@Getter +@Setter +@NoArgsConstructor +public class ApiStatusHist { + + @Id + @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "api_status_hist_seq") + @SequenceGenerator( + name = "api_status_hist_seq", + sequenceName = "API_STATUS_HIST_SEQ", + allocationSize = 1 + ) + @Column(name = "HIST_SEQ") + private Long histSeq; + + @Column(name = "EAISVCNAME", length = 30) + private String eaisvcname; + + @Column(name = "STATUS_CODE", length = 1) + private String statusCode; + + @Column(name = "PREV_STATUS_CODE", length = 1) + private String prevStatusCode; + + @Column(name = "JOBNAME", length = 40) + private String jobname; + + @Column(name = "INSTANCENAME", length = 20) + private String instancename; + + @Column(name = "CREATED_BY", length = 20) + private String createdBy; + + @Column(name = "CREATED_DATE") + private LocalDateTime createdDate; +} diff --git a/src/main/java/com/eactive/eai/rms/ext/djb/apistatus/hist/ApiStatusHistManController.java b/src/main/java/com/eactive/eai/rms/ext/djb/apistatus/hist/ApiStatusHistManController.java new file mode 100644 index 0000000..8ec5e50 --- /dev/null +++ b/src/main/java/com/eactive/eai/rms/ext/djb/apistatus/hist/ApiStatusHistManController.java @@ -0,0 +1,41 @@ +package com.eactive.eai.rms.ext.djb.apistatus.hist; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.data.web.SortDefault; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; + +import com.eactive.eai.rms.common.base.BaseAnnotationController; +import com.eactive.eai.rms.common.vo.GridResponse; + +import lombok.RequiredArgsConstructor; + +/** + * API 상태 변경 히스토리(API_STATUS_HIST) 조회 화면 컨트롤러. + * + *

조회 전용 (등록/수정/삭제 없음) - 데이터는 {@code ApiStatusService.updateApiStatus()}에서 + * 상태 전이가 감지될 때마다 자동 적재된다.

+ */ +@Controller +@RequiredArgsConstructor +public class ApiStatusHistManController extends BaseAnnotationController { + + private final ApiStatusHistManService apiStatusHistManService; + + @GetMapping(value = "/onl/apim/apistatus/hist/apiStatusHistMan.view") + public void view() { + // 목록 view + } + + @PostMapping(value = "/onl/apim/apistatus/hist/apiStatusHistMan.json", params = "cmd=LIST") + public ResponseEntity> selectList( + @SortDefault(sort = "createdDate", direction = Sort.Direction.DESC) Pageable pageable, + ApiStatusHistUISearch search) { + Page page = apiStatusHistManService.selectList(pageable, search); + return ResponseEntity.ok(new GridResponse<>(page)); + } +} diff --git a/src/main/java/com/eactive/eai/rms/ext/djb/apistatus/hist/ApiStatusHistManService.java b/src/main/java/com/eactive/eai/rms/ext/djb/apistatus/hist/ApiStatusHistManService.java new file mode 100644 index 0000000..0075c9b --- /dev/null +++ b/src/main/java/com/eactive/eai/rms/ext/djb/apistatus/hist/ApiStatusHistManService.java @@ -0,0 +1,75 @@ +package com.eactive.eai.rms.ext.djb.apistatus.hist; + +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.eactive.eai.rms.common.base.BaseService; +import com.eactive.eai.rms.common.util.StringUtils; +import com.eactive.eai.rms.data.entity.onl.djb.apistatus.hist.ApiStatusHist; +import com.eactive.eai.rms.data.entity.onl.djb.apistatus.hist.QApiStatusHist; +import com.querydsl.core.BooleanBuilder; + +import lombok.RequiredArgsConstructor; + +/** + * API 상태 변경 히스토리(API_STATUS_HIST) 조회 화면 서비스. 조회 전용. + */ +@Service +@RequiredArgsConstructor +@Transactional +public class ApiStatusHistManService extends BaseService { + + private static final DateTimeFormatter FMT_DATETIME = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + private static final DateTimeFormatter FMT_YYYYMMDD = DateTimeFormatter.ofPattern("yyyyMMdd"); + + private final ApiStatusHistRepository apiStatusHistRepository; + + public Page selectList(Pageable pageable, ApiStatusHistUISearch search) { + QApiStatusHist hist = QApiStatusHist.apiStatusHist; + BooleanBuilder predicate = new BooleanBuilder(); + + if (StringUtils.isNotBlank(search.getSearchEaisvcname())) { + predicate.and(hist.eaisvcname.containsIgnoreCase(search.getSearchEaisvcname())); + } + if (StringUtils.isNotBlank(search.getSearchStatusCode())) { + predicate.and(hist.statusCode.eq(search.getSearchStatusCode())); + } + if (StringUtils.isNotBlank(search.getSearchJobname())) { + predicate.and(hist.jobname.containsIgnoreCase(search.getSearchJobname())); + } + if (StringUtils.isNotBlank(search.getSearchInstancename())) { + predicate.and(hist.instancename.eq(search.getSearchInstancename())); + } + if (StringUtils.isNotBlank(search.getSearchStartDate())) { + predicate.and(hist.createdDate.goe(parseYYYYMMDD(search.getSearchStartDate()).atStartOfDay())); + } + if (StringUtils.isNotBlank(search.getSearchEndDate())) { + predicate.and(hist.createdDate.loe(parseYYYYMMDD(search.getSearchEndDate()).atTime(23, 59, 59))); + } + + Page page = apiStatusHistRepository.findAll(predicate, pageable); + return page.map(this::convertToUI); + } + + private static LocalDate parseYYYYMMDD(String yyyyMMdd) { + return LocalDate.parse(yyyyMMdd, FMT_YYYYMMDD); + } + + private ApiStatusHistUI convertToUI(ApiStatusHist e) { + ApiStatusHistUI ui = new ApiStatusHistUI(); + ui.setHistSeq(e.getHistSeq()); + ui.setEaisvcname(e.getEaisvcname()); + ui.setStatusCode(e.getStatusCode()); + ui.setPrevStatusCode(e.getPrevStatusCode()); + ui.setJobname(e.getJobname()); + ui.setInstancename(e.getInstancename()); + ui.setCreatedBy(e.getCreatedBy()); + ui.setCreatedDate(e.getCreatedDate() == null ? "" : e.getCreatedDate().format(FMT_DATETIME)); + return ui; + } +} diff --git a/src/main/java/com/eactive/eai/rms/ext/djb/apistatus/hist/ApiStatusHistRepository.java b/src/main/java/com/eactive/eai/rms/ext/djb/apistatus/hist/ApiStatusHistRepository.java new file mode 100644 index 0000000..de5644a --- /dev/null +++ b/src/main/java/com/eactive/eai/rms/ext/djb/apistatus/hist/ApiStatusHistRepository.java @@ -0,0 +1,10 @@ +package com.eactive.eai.rms.ext.djb.apistatus.hist; + +import org.springframework.stereotype.Repository; + +import com.eactive.eai.data.jpa.BaseRepository; +import com.eactive.eai.rms.data.entity.onl.djb.apistatus.hist.ApiStatusHist; + +@Repository +public interface ApiStatusHistRepository extends BaseRepository { +} diff --git a/src/main/java/com/eactive/eai/rms/ext/djb/apistatus/hist/ApiStatusHistUI.java b/src/main/java/com/eactive/eai/rms/ext/djb/apistatus/hist/ApiStatusHistUI.java new file mode 100644 index 0000000..2742591 --- /dev/null +++ b/src/main/java/com/eactive/eai/rms/ext/djb/apistatus/hist/ApiStatusHistUI.java @@ -0,0 +1,22 @@ +package com.eactive.eai.rms.ext.djb.apistatus.hist; + +import lombok.Data; + +/** + * API 상태 변경 히스토리(API_STATUS_HIST) 화면 응답 DTO. + * + *

상태코드(N/C/D/E)의 한글 라벨은 화면(JS)에서 매핑한다. 등록일시는 yyyy-MM-dd HH:mm:ss + * 형식 문자열로 제공한다.

+ */ +@Data +public class ApiStatusHistUI { + + private Long histSeq; + private String eaisvcname; + private String statusCode; + private String prevStatusCode; + private String jobname; + private String instancename; + private String createdBy; + private String createdDate; +} diff --git a/src/main/java/com/eactive/eai/rms/ext/djb/apistatus/hist/ApiStatusHistUISearch.java b/src/main/java/com/eactive/eai/rms/ext/djb/apistatus/hist/ApiStatusHistUISearch.java new file mode 100644 index 0000000..0376dbc --- /dev/null +++ b/src/main/java/com/eactive/eai/rms/ext/djb/apistatus/hist/ApiStatusHistUISearch.java @@ -0,0 +1,23 @@ +package com.eactive.eai.rms.ext.djb.apistatus.hist; + +import lombok.Data; + +@Data +public class ApiStatusHistUISearch { + + /* API ID(EAISVCNAME), LIKE 검색 */ + private String searchEaisvcname; + + /* 변경후 상태코드 (N/C/D/E, 공백=전체) */ + private String searchStatusCode; + + /* Job명(스케줄러 등록명), LIKE 검색 */ + private String searchJobname; + + /* 실행 인스턴스명 */ + private String searchInstancename; + + /* 등록일시 기간 검색 (yyyyMMdd, 8자리) */ + private String searchStartDate; + private String searchEndDate; +}