var ReportWeeklyApi = (function () { "use strict" let selectedYearWeek = { "year": null, "week": null } // Time // Time API -> // 1. 일정 진행도 (차트) // 2. 일정 준수율 // 3. 지연된 일정의 수 var time_data = { "start_date" : null, "end_date" : null, "current_date" : null, "week_number" : 1, // 주차 } // Scope // 1. 금주 완료 증감 // 2. 신규 추가 건수 // 3. 요구사항 현황 (차트) var scope_data = { "total" : 0, // 총합 "folder" : 0, // 폴더타입 "not-open" : 0, // 열림 제외(진행중, 해결됨, 닫힘) "resolved-and-closed" : 0, // 해결됨+닫힘 "open" : 0, // 열림 "in-progress" : 0, // 진행중 "resolved" : 0, // 해결됨 "closed" : 0 // 닫힘 } // Resource // 1. 총 가동인원 // 2. 금주 작업 인원 // 3. Top3 기여자 // 인당 처리량 -> 금주 var resource = { "total_resource": 0, "active_resource": 0, // 금주 작업 인원 "total_avg": 0, "top3_resource": "" // 동점 포함? } // ========== 공통 함수 ========== function splitYearWeek(selectedWeek) { if (selectedWeek) { let [year, week] = selectedWeek.split("-W"); selectedYearWeek.year = year; selectedYearWeek.week = week; } } function formatDate(date) { if (!(date instanceof Date)) { date = new Date(date); } const year = date.getFullYear(); const month = (date.getMonth() + 1).toString().padStart(2, "0"); const day = date.getDate().toString().padStart(2, "0"); return `${year}-${month}-${day}`; } function buildRequestDTO(pdServiceId, pdServiceName,pdServiceVersionLinks, startDate, endDate) { return { "pdServiceId": pdServiceId, "pdServiceName": pdServiceName, "pdServiceVersions": pdServiceVersionLinks.split(',').map(Number), "reportYear": selectedYearWeek.year, "reportWeek": selectedYearWeek.week, "weekStartDate": formatDate(startDate), "weekEndDate": formatDate(endDate) }; } function fetchWeeklyData(endpoint, requestDTO) { return $.ajax({ url: `/auth-user/api/arms/report/weekly/${endpoint}`, type: "POST", data: JSON.stringify(requestDTO), contentType: "application/json;charset=UTF-8", dataType: "json", progress: true }); } // ========== 개별 API 호출 ========== var fetchTimeData = function (requestDTO) { return fetchWeeklyData("time", requestDTO); } var fetchScopeData = function (requestDTO) { return fetchWeeklyData("scope", requestDTO); } var fetchResourceData = function (requestDTO) { return fetchWeeklyData("resource", requestDTO); } // 이전 Blob URL을 저장 (메모리 누수 방지용) var previousBlobUrl = null; var fetchPDF = function (pdServiceId, pdServiceName, pdServiceVersionLinks, selectedWeek, startDate, endDate, displayMode) { splitYearWeek(selectedWeek); let dto = buildRequestDTOPDF(pdServiceId, pdServiceName, pdServiceVersionLinks, startDate, endDate, displayMode); // byte[] 다운로드를 위해 blob 타입으로 요청 return $.ajax({ url: `/auth-user/api/arms/report/weekly/export/pdf`, type: "POST", data: JSON.stringify(dto), contentType: "application/json;charset=UTF-8", xhrFields: { responseType: 'blob' // binary 데이터 수신 }, success: function(blob, status, xhr) { // 이전 Blob URL 해제 (메모리 누수 방지) if (previousBlobUrl) { URL.revokeObjectURL(previousBlobUrl); } // Blob URL 생성 var blobUrl = URL.createObjectURL(blob); previousBlobUrl = blobUrl; // PDF.js viewer에 Blob URL 전달 var viewerBaseUrl = "../reference/jquery-plugins/pdfjs-3.11.174-dist/web/viewer.html"; var viewerUrl = viewerBaseUrl + "?file=" + encodeURIComponent(blobUrl) + "#zoom=page-width"; // iframe src 업데이트 $("#pdf-viewer-iframe").attr("src", viewerUrl); // 다운로드 버튼 업데이트 var contentDisposition = xhr.getResponseHeader('Content-Disposition'); var filename = "WeeklyReport_" + selectedYearWeek.year + "W" + selectedYearWeek.week + ".pdf"; if (contentDisposition) { var filenameMatch = contentDisposition.match(/filename\*?=(?:UTF-8'')?["']?([^"';\n]+)["']?/i); if (filenameMatch && filenameMatch[1]) { filename = decodeURIComponent(filenameMatch[1]); } } $("#btn-pdf-download") .attr("href", blobUrl) .attr("download", filename); console.log("[ ReportWeeklyApi :: fetchPDF ] :: PDF 로드 완료 => ", filename); }, error: function(xhr, status, error) { console.error("[ ReportWeeklyApi :: fetchPDF ] :: 가져오기 실패 => ", error); jError("PDF 파일 가져오기에 실패했습니다."); } }); } function buildRequestDTOPDF(pdServiceId, pdServiceName,pdServiceVersionLinks, startDate, endDate, displayMode) { return { "pdServiceId": pdServiceId, "pdServiceName": pdServiceName, "pdServiceVersions": pdServiceVersionLinks.split(',').map(Number), "reportYear": selectedYearWeek.year, "reportWeek": selectedYearWeek.week, "weekStartDate": formatDate(startDate), "weekEndDate": formatDate(endDate), "display": displayMode }; } var fetchExportPPT = function (pdServiceId, pdServiceName, pdServiceVersionLinks, selectedWeek, startDate, endDate) { splitYearWeek(selectedWeek); let dto = buildRequestDTO(pdServiceId, pdServiceName, pdServiceVersionLinks, startDate, endDate); // byte[] 다운로드를 위해 blob 타입으로 요청 return $.ajax({ url: `/auth-user/api/arms/report/weekly/export`, type: "POST", data: JSON.stringify(dto), contentType: "application/json;charset=UTF-8", xhrFields: { responseType: 'blob' // binary 데이터 수신 }, success: function(blob, status, xhr) { // Content-Disposition 헤더에서 파일명 추출 var contentDisposition = xhr.getResponseHeader('Content-Disposition'); var filename = "WeeklyReport.pptx"; if (contentDisposition) { var filenameMatch = contentDisposition.match(/filename\*?=(?:UTF-8'')?["']?([^"';\n]+)["']?/i); if (filenameMatch && filenameMatch[1]) { filename = decodeURIComponent(filenameMatch[1]); } } // Blob URL 생성 및 다운로드 var downloadUrl = URL.createObjectURL(blob); var a = document.createElement('a'); a.href = downloadUrl; a.download = filename; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(downloadUrl); console.log("[ ReportWeeklyApi :: fetchExportPPT ] :: 다운로드 완료 => ", filename); }, error: function(xhr, status, error) { console.error("[ ReportWeeklyApi :: fetchExportPPT ] :: 다운로드 실패 => ", error); jError("PPTX 다운로드에 실패했습니다."); } }); } // ========== 통합 API 호출 ========== var fetchAllWeeklyData = function (pdServiceId, pdServiceName, pdServiceVersionLinks, selectedWeek, startDate, endDate) { splitYearWeek(selectedWeek); console.log("[ ReportWeeklyApi :: fetchAllWeeklyData ] :: pdServiceId => ", pdServiceId); console.log("[ ReportWeeklyApi :: fetchAllWeeklyData ] :: pdServiceName => ", pdServiceName); console.log("[ ReportWeeklyApi :: fetchAllWeeklyData ] :: pdServiceVersionLinks => ", pdServiceVersionLinks); console.log("[ ReportWeeklyApi :: fetchAllWeeklyData ] :: selectedWeek => ", selectedYearWeek.year + "-W" + selectedYearWeek.week); console.log("[ ReportWeeklyApi :: fetchAllWeeklyData ] :: startDate => ", startDate); console.log("[ ReportWeeklyApi :: fetchAllWeeklyData ] :: endDate => ", endDate); const requestDTO = buildRequestDTO(pdServiceId, pdServiceName, pdServiceVersionLinks, startDate, endDate); return Promise.all([ fetchTimeData(requestDTO), fetchScopeData(requestDTO), fetchResourceData(requestDTO) ]).then(([timeResult, scopeResult, resourceResult]) => { console.log("[ ReportWeeklyApi :: fetchAllWeeklyData ] :: timeResult => ", timeResult); console.log("[ ReportWeeklyApi :: fetchAllWeeklyData ] :: scopeResult => ", scopeResult); console.log("[ ReportWeeklyApi :: fetchAllWeeklyData ] :: resourceResult => ", resourceResult); return { time: timeResult, scope: scopeResult, resource: resourceResult }; }); } return { fetchTimeData, fetchScopeData, fetchResourceData, fetchAllWeeklyData, buildRequestDTO, splitYearWeek, fetchExportPPT, fetchPDF }; })(); // 즉시 실행 함수