package com.eactive.ext.kjb.statistics; import java.io.IOException; import java.time.YearMonth; import java.time.format.DateTimeFormatter; import java.util.List; import java.util.Map; import java.util.Set; import java.util.stream.Collectors; import javax.servlet.http.HttpServletResponse; import org.apache.commons.lang3.StringUtils; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; 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.datasource.DataSourceContextHolder; import com.eactive.eai.rms.common.datasource.DataSourceTypeManager; import com.eactive.eai.rms.common.vo.GridResponse; import com.eactive.eai.rms.data.entity.onl.apim.obp.ObpGwMetricJpaDAO; import com.eactive.eai.rms.data.entity.onl.kjb.statistics.ApiStatsMonth; import com.eactive.eai.rms.data.entity.onl.kjb.statistics.ApiStatsMonthService; import com.eactive.ext.kjb.statistics.mapping.ApiStatsUIMapper; import com.eactive.ext.kjb.statistics.service.ApiStatsExcelExportService; import com.eactive.ext.kjb.statistics.ui.ApiStatsChartUI; import com.eactive.ext.kjb.statistics.ui.ApiStatsSearch; import com.eactive.ext.kjb.statistics.ui.ApiStatsUI; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @Slf4j @Controller @RequiredArgsConstructor public class ApiStatsMonthController { private final ApiStatsMonthService service; private final ApiStatsUIMapper mapper; private final ApiStatsExcelExportService excelExportService; private final ObpGwMetricJpaDAO apiNameDao; @GetMapping(value = "/onl/kjb/statistics/apiStatsMonthMan.view") public String view() { return "/onl/kjb/statistics/apiStatsMonthMan"; } @PostMapping(value = "/onl/kjb/statistics/apiStatsMonthMan.json", params = "cmd=LIST") public ResponseEntity> selectList(ApiStatsSearch search, Pageable pageable) { Pageable sortedPageable = PageRequest.of( pageable.getPageNumber(), pageable.getPageSize(), Sort.by(Sort.Order.desc("statTime"))); Page page = service.selectList(search, sortedPageable); Page uiPage = page.map(mapper::toVo); return ResponseEntity.ok(new GridResponse<>(uiPage)); } @PostMapping(value = "/onl/kjb/statistics/apiStatsMonthMan.json", params = "cmd=CHART") public ResponseEntity> selectChartData(ApiStatsSearch search) { List chartData = service.selectChartData(search); return ResponseEntity.ok(chartData); } @PostMapping(value = "/onl/kjb/statistics/apiStatsMonthMan.json", params = "cmd=LIST_SUMMARY") public ResponseEntity> selectSummaryList(ApiStatsSearch search, Pageable pageable) { Page page = service.selectSummaryList(search, pageable); fillApiDesc(page.getContent()); return ResponseEntity.ok(new GridResponse<>(page)); } /** * 요약 통계 행의 apiName(=API ID)으로 TSEAIHE01 을 조회하여 API 명(EAISVCDESC)을 채운다. * 매칭되는 항목이 없으면 공란으로 둔다. */ private void fillApiDesc(List rows) { if (rows == null || rows.isEmpty()) { return; } Set apiIds = rows.stream() .map(ApiStatsUI::getApiName) .filter(id -> id != null && !id.isEmpty()) .collect(Collectors.toSet()); if (apiIds.isEmpty()) { return; } // API_STATS_MONTH 와 동일한 APIGW 스키마에서 조회 DataSourceContextHolder.setDataSourceType( DataSourceTypeManager.getDataSourceType(DataSourceTypeManager.APIGW)); Map nameMap = apiNameDao.selectApiNames(apiIds); for (ApiStatsUI row : rows) { row.setApiDesc(nameMap.get(row.getApiName())); } } @PostMapping(value = "/onl/kjb/statistics/apiStatsMonthMan.json", params = "cmd=EXCEL_EXPORT") public void exportToExcel(ApiStatsSearch search, HttpServletResponse response) throws IOException { log.info("Excel export started - search: {}", search); try { List dataList = service.selectListForExcel(search); log.info("Data retrieved - count: {}", dataList.size()); if (dataList.isEmpty()) { log.warn("No data found for export"); response.setStatus(HttpServletResponse.SC_NO_CONTENT); response.setContentType("application/json; charset=UTF-8"); response.getWriter().write("{\"message\":\"조회된 데이터가 없습니다.\"}"); response.getWriter().flush(); return; } List uiList = dataList.stream() .map(mapper::toVo) .collect(Collectors.toList()); log.info("Data converted to UI list - count: {}", uiList.size()); String fileName = generateFileName(search); log.info("Generating Excel file: {}", fileName); excelExportService.exportApiStats(uiList, fileName, response); log.info("Excel export completed successfully"); } catch (Exception e) { log.error("Excel export failed - error: {}", e.getMessage(), e); if (!response.isCommitted()) { response.reset(); response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); response.setContentType("application/json; charset=UTF-8"); response.getWriter().write("{\"message\":\"Excel 파일 생성 중 오류가 발생했습니다: " + e.getMessage() + "\"}"); response.getWriter().flush(); } else { log.error("Cannot send error response - response already committed"); } } } @PostMapping(value = "/onl/kjb/statistics/apiStatsMonthMan.json", params = "cmd=EXCEL_EXPORT_SUMMARY") public void exportSummaryToExcel(ApiStatsSearch search, HttpServletResponse response) throws IOException { log.info("Excel export (summary) started - search: {}", search); try { List dataList = service.selectSummaryListForExcel(search); log.info("Summary data retrieved - count: {}", dataList.size()); if (dataList.isEmpty()) { log.warn("No data found for export"); response.setStatus(HttpServletResponse.SC_NO_CONTENT); response.setContentType("application/json; charset=UTF-8"); response.getWriter().write("{\"message\":\"조회된 데이터가 없습니다.\"}"); response.getWriter().flush(); return; } String fileName = generateSummaryFileName(search); log.info("Generating Excel file: {}", fileName); excelExportService.exportApiStats(dataList, fileName, response); log.info("Excel export (summary) completed successfully"); } catch (Exception e) { log.error("Excel export (summary) failed - error: {}", e.getMessage(), e); if (!response.isCommitted()) { response.reset(); response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); response.setContentType("application/json; charset=UTF-8"); response.getWriter().write("{\"message\":\"Excel 파일 생성 중 오류가 발생했습니다: " + e.getMessage() + "\"}"); response.getWriter().flush(); } else { log.error("Cannot send error response - response already committed"); } } } private String generateFileName(ApiStatsSearch search) { String timeRange = StringUtils.isNotBlank(search.getSearchStartDateTime()) ? search.getSearchStartDateTime() : YearMonth.now().format(DateTimeFormatter.ofPattern("yyyyMM")); return "API월별통계_" + timeRange + ".xlsx"; } private String generateSummaryFileName(ApiStatsSearch search) { String timeRange = StringUtils.isNotBlank(search.getSearchStartDateTime()) ? search.getSearchStartDateTime() : YearMonth.now().format(DateTimeFormatter.ofPattern("yyyyMM")); return "API월별통계_요약_" + timeRange + ".xlsx"; } }