package com.interplug.qcast.biz.community; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.interplug.qcast.biz.community.dto.BoardRequest; import com.interplug.qcast.biz.community.dto.BoardResponse; import com.interplug.qcast.biz.estimate.dto.EstimateApiResponse; import com.interplug.qcast.biz.file.dto.FileRequest; import com.interplug.qcast.config.Exception.ErrorCode; import com.interplug.qcast.config.Exception.QcastException; import com.interplug.qcast.config.message.Messages; import com.interplug.qcast.util.InterfaceQsp; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.core.io.InputStreamResource; import org.springframework.http.*; import org.springframework.http.converter.xml.MappingJackson2XmlHttpMessageConverter; import org.springframework.stereotype.Service; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.StreamUtils; import org.springframework.web.client.RestTemplate; import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartHttpServletRequest; import org.springframework.web.util.UriComponentsBuilder; @Slf4j @Service @RequiredArgsConstructor public class BoardService { private final InterfaceQsp interfaceQsp; @Autowired Messages message; @Value("${qsp.url}") private String QSP_API_URL; /** * ※ 게시판 목록 조회 QSP -> Q.CAST3 * * @param boardRequest * @return * @throws Exception */ public BoardResponse getBoardList(BoardRequest boardRequest) throws Exception { BoardResponse response = null; /* [0]. Validation Check */ if ("".equals(boardRequest.getSchNoticeClsCd())) { // [msg] {0} is required input value. throw new QcastException( ErrorCode.INVALID_INPUT_VALUE, message.getMessage("common.message.required.data", "Notice Cls Code")); } if ("".equals(boardRequest.getSchNoticeTpCd())) { // [msg] {0} is required input value. throw new QcastException( ErrorCode.INVALID_INPUT_VALUE, message.getMessage("common.message.required.data", "Notice Type Code")); } /* [1]. QSP API (url + param) Setting */ String encodedSchTitle = ""; if (!"".equals(boardRequest.getSchTitle()) && boardRequest.getSchTitle() != null) { encodedSchTitle = URLEncoder.encode(boardRequest.getSchTitle(), StandardCharsets.UTF_8); } String url = null; String apiUrl = null; if("QNA".equals(boardRequest.getSchNoticeClsCd())) { url = QSP_API_URL + "/api/qna/list"; apiUrl = UriComponentsBuilder.fromHttpUrl(url) .queryParam("compCd", boardRequest.getCompCd()) .queryParam("storeId", boardRequest.getStoreId()) .queryParam("siteTpCd", boardRequest.getSiteTpCd()) .queryParam("schTitle", encodedSchTitle) .queryParam("schRegId", boardRequest.getSchRegId()) .queryParam("schFromDt", boardRequest.getSchFromDt()) .queryParam("schToDt", boardRequest.getSchToDt()) .queryParam("startRow", boardRequest.getStartRow()) .queryParam("endRow", boardRequest.getEndRow()) .queryParam("loginId", boardRequest.getLoginId()) .queryParam("langCd", boardRequest.getLangCd()) .build() .toUriString(); } else { url = QSP_API_URL + "/api/board/list"; apiUrl = UriComponentsBuilder.fromHttpUrl(url) .queryParam("noticeNo", boardRequest.getNoticeNo()) .queryParam("schTitle", encodedSchTitle) .queryParam("schNoticeTpCd", boardRequest.getSchNoticeTpCd()) .queryParam("schNoticeClsCd", boardRequest.getSchNoticeClsCd()) .queryParam("startRow", boardRequest.getStartRow()) .queryParam("endRow", boardRequest.getEndRow()) .queryParam("schMainYn", boardRequest.getSchMainYn()) .build() .toUriString(); } /* [2]. QSP API CALL -> Response */ String strResponse = interfaceQsp.callApi(HttpMethod.GET, apiUrl, null); if (!"".equals(strResponse)) { ObjectMapper om = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); response = om.readValue(strResponse, BoardResponse.class); } else { // [msg] No data throw new QcastException(ErrorCode.NOT_FOUND, message.getMessage("common.message.no.data")); } return response; } /** * ※ 게시판 상세 조회 QSP -> Q.CAST3 * * @param boardRequest * @return * @throws Exception */ public BoardResponse getBoardDetail(BoardRequest boardRequest) throws Exception { BoardResponse response = null; /* [0]. Validation Check */ if (boardRequest.getNoticeNo() == null) { // [msg] {0} is required input value. throw new QcastException( ErrorCode.INVALID_INPUT_VALUE, message.getMessage("common.message.required.data", "Notice No")); } String url = null; String apiUrl = null; if("QNA".equals(boardRequest.getSchNoticeClsCd())) { url = QSP_API_URL + "/api/qna/detail"; apiUrl = UriComponentsBuilder.fromHttpUrl(url) .queryParam("qnaNo", boardRequest.getQnaNo()) .queryParam("compCd", boardRequest.getCompCd()) .queryParam("loginId", boardRequest.getLoginId()) .queryParam("langCd", boardRequest.getLangCd()) .queryParam("siteTpCd", boardRequest.getSiteTpCd()) .build() .toUriString(); } else { /* [1]. QSP API (url + param) Setting */ url = QSP_API_URL + "/api/board/detail"; apiUrl = UriComponentsBuilder.fromHttpUrl(url) .queryParam("noticeNo", boardRequest.getNoticeNo()) .build() .toUriString(); } /* [2]. QSP API CALL -> Response */ String strResponse = interfaceQsp.callApi(HttpMethod.GET, apiUrl, null); if (!"".equals(strResponse)) { ObjectMapper om = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); response = om.readValue(strResponse, BoardResponse.class); } else { // [msg] No data throw new QcastException(ErrorCode.NOT_FOUND, message.getMessage("common.message.no.data")); } return response; } /** * ※ 게시판 저장 QSP -> Q.CAST3 * * @param boardRequest * @return * @throws Exception */ public BoardResponse getBoardQnaSave(BoardRequest boardRequest, HttpServletRequest request) throws Exception { BoardResponse response = null; /* [0]. Validation Check */ if (boardRequest.getCompCd() == null || boardRequest.getCompCd().isEmpty()) { // [msg] {0} is required input value. throw new QcastException( ErrorCode.INVALID_INPUT_VALUE, message.getMessage("common.message.required.data", "Comp Cd")); } if (boardRequest.getSiteTpCd() == null || boardRequest.getSiteTpCd().isEmpty()) { // [msg] {0} is required input value. throw new QcastException( ErrorCode.INVALID_INPUT_VALUE, message.getMessage("common.message.required.data", "Site Type Cd")); } if (boardRequest.getQnaClsLrgCd() == null || boardRequest.getQnaClsLrgCd().isEmpty()) { // [msg] {0} is required input value. throw new QcastException( ErrorCode.INVALID_INPUT_VALUE, message.getMessage("common.message.required.data", "Qna Cls Large Cd")); } if (boardRequest.getQnaClsMidCd() == null || boardRequest.getQnaClsMidCd().isEmpty()) { // [msg] {0} is required input value. throw new QcastException( ErrorCode.INVALID_INPUT_VALUE, message.getMessage("common.message.required.data", "Qna Cls Mid Cd")); } if (boardRequest.getTitle() == null || boardRequest.getTitle().isEmpty()) { // [msg] {0} is required input value. throw new QcastException( ErrorCode.INVALID_INPUT_VALUE, message.getMessage("common.message.required.data", "title")); } if (boardRequest.getContents() == null || boardRequest.getContents().isEmpty()) { // [msg] {0} is required input value. throw new QcastException( ErrorCode.INVALID_INPUT_VALUE, message.getMessage("common.message.required.data", "contents")); } if (boardRequest.getRegId() == null || boardRequest.getRegId().isEmpty()) { // [msg] {0} is required input value. throw new QcastException( ErrorCode.INVALID_INPUT_VALUE, message.getMessage("common.message.required.data", "Reg Id")); } if (boardRequest.getRegUserNm() == null || boardRequest.getRegUserNm().isEmpty()) { // [msg] {0} is required input value. throw new QcastException( ErrorCode.INVALID_INPUT_VALUE, message.getMessage("common.message.required.data", "Reg User Nm")); } String url = null; String apiUrl = null; BoardResponse boardResponse = null; if("QNA".equals(boardRequest.getSchNoticeClsCd())) { url = QSP_API_URL + "/api/qna/save"; apiUrl = UriComponentsBuilder.fromHttpUrl(url) .queryParam("siteTpCd", boardRequest.getSiteTpCd()) .queryParam("compCd", boardRequest.getCompCd()) .queryParam("regId", boardRequest.getRegId()) .queryParam("title", boardRequest.getTitle()) .queryParam("qnaClsLrgCd", boardRequest.getQnaClsLrgCd() ) .queryParam("qnaClsMidCd", boardRequest.getQnaClsMidCd()) .queryParam("qnaClsSmlCd", boardRequest.getQnaClsSmlCd()) .queryParam("contents", boardRequest.getContents()) .queryParam("storeId", boardRequest.getStoreId()) .queryParam("regUserNm", boardRequest.getRegUserNm()) .queryParam("regUserTelNo", boardRequest.getRegUserTelNo()) .queryParam("qstMail", boardRequest.getQstMail()) // .queryParam("files", multipartFileList) .build() .toUriString(); } List multipartFileList = new ArrayList<>(); MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request; Map> mapMultipart = multipartRequest.getMultiFileMap(); String strParamKey; for (String s : mapMultipart.keySet()) { strParamKey = s; multipartFileList.addAll(mapMultipart.get(strParamKey)); } LinkedMultiValueMap map = new LinkedMultiValueMap<>(); RestTemplate restTemplate = new RestTemplate(); String responseStr; HttpStatus httpStatus = HttpStatus.CREATED; for (MultipartFile file : multipartFileList) { if (!file.isEmpty()) { map.add("file", new MultipartInputStreamFileResource(file.getInputStream(), file.getOriginalFilename())); } } HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.MULTIPART_FORM_DATA); HttpEntity> requestEntity = new HttpEntity<>(map, headers); String strResponse = restTemplate.postForObject(apiUrl, requestEntity, String.class); //String strResponse = interfaceQsp.callApi(HttpMethod.POST, apiUrl, multipartFileList); if (!"".equals(strResponse)) { com.fasterxml.jackson.databind.ObjectMapper om = new com.fasterxml.jackson.databind.ObjectMapper() .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); response = om.readValue(strResponse, BoardResponse.class); } else { // [msg] No data throw new QcastException(ErrorCode.NOT_FOUND, message.getMessage("common.message.no.data")); } return response; } /** * ※ 게시판 파일 다운로드 QSP -> Q.CAST3 * * @param response * @param encodeFileNo * @throws Exception */ public void getFileDownload(HttpServletResponse response, String keyNo, String zipYn) throws Exception { /* [0]. Validation Check */ if ("".equals(keyNo)) { // [msg] {0} is required input value. String arg = "Y".equals(zipYn) ? "Notice No" : "File No"; throw new QcastException( ErrorCode.INVALID_INPUT_VALUE, message.getMessage("common.message.required.data", arg)); } /* [1]. QSP API (url + fileNo) Setting */ String url = null; if("NO".equals(zipYn)) { url = QSP_API_URL + "/api/file/downloadFile2?encodeFileNo=" + keyNo; }else{ url = QSP_API_URL + "/api/file/downloadFile"; if ("Y".equals(zipYn)) { url += "?noticeNo=" + keyNo; } else { url += "?fileNo=" + keyNo; } } /* [2]. QSP API CALL -> Response */ Map result = new HashMap(); byte[] byteResponse = interfaceQsp.callApi(HttpMethod.GET, url, null, result); if (byteResponse != null && byteResponse.length > 0) { try { /* [3]. API 응답 파일 처리 */ response.addHeader("Access-Control-Expose-Headers", "Content-Disposition"); response.setContentType( !"".equals(result.get("type")) && result.get("type") != null ? result.get("type") : "application/octet-stream"); response.setHeader( "Content-Disposition", !"".equals(result.get("disposition")) && result.get("disposition") != null ? result.get("disposition") : "attachment;"); InputStream inputStream = new ByteArrayInputStream(byteResponse); StreamUtils.copy(inputStream, response.getOutputStream()); response.flushBuffer(); inputStream.close(); } catch (Exception e) { // [msg] File download error throw new QcastException( ErrorCode.INTERNAL_SERVER_ERROR, message.getMessage("common.message.file.download.error")); } } else { // [msg] File does not exist. throw new QcastException( ErrorCode.NOT_FOUND, message.getMessage("common.message.file.download.exists")); } } } class MultipartInputStreamFileResource extends InputStreamResource { private final String filename; MultipartInputStreamFileResource(InputStream inputStream, String filename) { super(inputStream); this.filename = filename; } @Override public String getFilename() { return this.filename; } @Override public long contentLength() throws IOException { return -1; // we do not want to generally read the whole stream into memory ... } }