Compare commits

...

4 Commits

10 changed files with 318 additions and 44 deletions

3
.gitignore vendored
View File

@ -35,4 +35,5 @@ build/
.vscode/ .vscode/
### logs ### ### logs ###
qcast3/ qcast3/
src/test

View File

@ -2,18 +2,15 @@ package com.interplug.qcast.biz.community;
import com.interplug.qcast.biz.community.dto.BoardRequest; import com.interplug.qcast.biz.community.dto.BoardRequest;
import com.interplug.qcast.biz.community.dto.BoardResponse; import com.interplug.qcast.biz.community.dto.BoardResponse;
import com.interplug.qcast.biz.file.dto.FileRequest;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
@Slf4j @Slf4j
@RestController @RestController
@ -38,6 +35,13 @@ public class BoardController {
return boardService.getBoardDetail(boardRequest); return boardService.getBoardDetail(boardRequest);
} }
@Operation(description = "문의를 저장한다.")
@PostMapping("/saveQna")
@ResponseStatus(HttpStatus.OK)
public BoardResponse getBoardQnaSave(BoardRequest boardRequest, HttpServletRequest request) throws Exception {
return boardService.getBoardQnaSave(boardRequest, request);
}
@Operation(description = "커뮤니티(공지사항, FAQ, 자료다운로드) 파일 다운로드를 진행한다.") @Operation(description = "커뮤니티(공지사항, FAQ, 자료다운로드) 파일 다운로드를 진행한다.")
@GetMapping("/file/download") @GetMapping("/file/download")
@ResponseStatus(HttpStatus.OK) @ResponseStatus(HttpStatus.OK)

View File

@ -4,24 +4,36 @@ import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.interplug.qcast.biz.community.dto.BoardRequest; import com.interplug.qcast.biz.community.dto.BoardRequest;
import com.interplug.qcast.biz.community.dto.BoardResponse; 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.ErrorCode;
import com.interplug.qcast.config.Exception.QcastException; import com.interplug.qcast.config.Exception.QcastException;
import com.interplug.qcast.config.message.Messages; import com.interplug.qcast.config.message.Messages;
import com.interplug.qcast.util.InterfaceQsp; import com.interplug.qcast.util.InterfaceQsp;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.net.URLEncoder; import java.net.URLEncoder;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpMethod; 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.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.StreamUtils; 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; import org.springframework.web.util.UriComponentsBuilder;
@Slf4j @Slf4j
@ -66,18 +78,39 @@ public class BoardService {
encodedSchTitle = URLEncoder.encode(boardRequest.getSchTitle(), StandardCharsets.UTF_8); encodedSchTitle = URLEncoder.encode(boardRequest.getSchTitle(), StandardCharsets.UTF_8);
} }
String url = QSP_API_URL + "/api/board/list"; String url = null;
String apiUrl = String apiUrl = null;
UriComponentsBuilder.fromHttpUrl(url)
.queryParam("noticeNo", boardRequest.getNoticeNo()) if("QNA".equals(boardRequest.getSchNoticeClsCd())) {
.queryParam("schTitle", encodedSchTitle) url = QSP_API_URL + "/api/qna/list";
.queryParam("schNoticeTpCd", boardRequest.getSchNoticeTpCd()) apiUrl = UriComponentsBuilder.fromHttpUrl(url)
.queryParam("schNoticeClsCd", boardRequest.getSchNoticeClsCd()) .queryParam("compCd", boardRequest.getCompCd())
.queryParam("startRow", boardRequest.getStartRow()) .queryParam("storeId", boardRequest.getStoreId())
.queryParam("endRow", boardRequest.getEndRow()) .queryParam("siteTpCd", boardRequest.getSiteTpCd())
.queryParam("schMainYn", boardRequest.getSchMainYn()) .queryParam("schTitle", encodedSchTitle)
.build() .queryParam("schRegId", boardRequest.getSchRegId())
.toUriString(); .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 */ /* [2]. QSP API CALL -> Response */
String strResponse = interfaceQsp.callApi(HttpMethod.GET, apiUrl, null); String strResponse = interfaceQsp.callApi(HttpMethod.GET, apiUrl, null);
@ -114,14 +147,26 @@ public class BoardService {
message.getMessage("common.message.required.data", "Notice No")); message.getMessage("common.message.required.data", "Notice No"));
} }
/* [1]. QSP API (url + param) Setting */ String url = null;
String url = QSP_API_URL + "/api/board/detail"; String apiUrl = null;
String apiUrl =
UriComponentsBuilder.fromHttpUrl(url)
.queryParam("noticeNo", boardRequest.getNoticeNo())
.build()
.toUriString();
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())
.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 */ /* [2]. QSP API CALL -> Response */
String strResponse = interfaceQsp.callApi(HttpMethod.GET, apiUrl, null); String strResponse = interfaceQsp.callApi(HttpMethod.GET, apiUrl, null);
@ -138,6 +183,138 @@ public class BoardService {
return response; 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<MultipartFile> multipartFileList = new ArrayList<>();
MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
Map<String, List<MultipartFile>> mapMultipart = multipartRequest.getMultiFileMap();
String strParamKey;
for (String s : mapMultipart.keySet()) {
strParamKey = s;
multipartFileList.addAll(mapMultipart.get(strParamKey));
}
LinkedMultiValueMap<String, Object> 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<LinkedMultiValueMap<String, Object>> 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 * 게시판 파일 다운로드 QSP -> Q.CAST3
* *
@ -202,3 +379,23 @@ public class BoardService {
} }
} }
} }
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 ...
}
}

View File

@ -1,7 +1,13 @@
package com.interplug.qcast.biz.community.dto; package com.interplug.qcast.biz.community.dto;
import com.interplug.qcast.biz.file.dto.FileRequest;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.servlet.http.HttpServletRequest;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import org.springframework.web.multipart.MultipartFile;
import java.util.List;
@Getter @Getter
@Setter @Setter
@ -28,4 +34,37 @@ public class BoardRequest {
/** 메인여부 */ /** 메인여부 */
private String schMainYn; private String schMainYn;
//Company Code
private String compCd;
private String storeId;
//Site Type Code
private String siteTpCd;
private String loginId;
//등록자 아이디
private String schRegId;
//검색 시작일시
private String schFromDt;
//검색 끝일시
private String schToDt;
private String qnaNo;
private String langCd;
private String qnaClsLrgCd;
private String qnaClsMidCd;
private String qnaClsSmlCd;
private String contents;
private String regId;
private String title;
private String regUserNm;
private String regUserTelNo;
private String qstMail;
@Schema(description = "첨부파일 목록")
List<MultipartFile> fileList;
} }

View File

@ -4,11 +4,13 @@ import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info; import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.media.StringSchema; import io.swagger.v3.oas.models.media.StringSchema;
import io.swagger.v3.oas.models.parameters.Parameter; import io.swagger.v3.oas.models.parameters.Parameter;
import io.swagger.v3.oas.models.servers.Server;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springdoc.core.customizers.OpenApiCustomizer; import org.springdoc.core.customizers.OpenApiCustomizer;
import org.springdoc.core.models.GroupedOpenApi; import org.springdoc.core.models.GroupedOpenApi;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment; import org.springframework.core.env.Environment;
@ -20,30 +22,51 @@ public class SwaggerConfig {
@Autowired Environment env; @Autowired Environment env;
@Value("${swagger.url}")
private String swaggerUrl;
@Bean @Bean
public OpenAPI baseApi() { public OpenAPI baseApi() {
String activeProfile = env.getProperty("spring.profiles.active"); String activeProfile = env.getProperty("spring.profiles.active");
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug("Active profile: {}", activeProfile); log.debug("Active profile: {}", activeProfile);
} }
Server server = new Server();
server.setUrl(swaggerUrl);
OpenAPI openAPI = new OpenAPI(); OpenAPI openAPI = new OpenAPI();
openAPI.info( openAPI
new Info().title("QCast API").version("1.0").description("QCast API Documentation")); .info(new Info().title("QCast API").version("1.0").description("QCast API Documentation"))
.addServersItem(server);
return openAPI; return openAPI;
} }
@Bean @Bean
public GroupedOpenApi allApi() { public GroupedOpenApi allApi() {
return GroupedOpenApi.builder().group("ALL").packagesToScan("com.interplug.qcast.biz").addOpenApiCustomizer(openApiCustomizer()).build(); return GroupedOpenApi.builder()
.group("ALL")
.packagesToScan("com.interplug.qcast.biz")
.addOpenApiCustomizer(openApiCustomizer())
.build();
} }
@Bean @Bean
public OpenApiCustomizer openApiCustomizer() { public OpenApiCustomizer openApiCustomizer() {
Parameter lang = new Parameter().name("lang").description("Language").in("header").schema(new StringSchema()); Parameter lang =
return openApi -> openApi.getPaths().values().forEach( new Parameter()
pathItem -> pathItem.readOperations().forEach( .name("lang")
operation -> operation.addParametersItem(lang) .description("Language")
) .in("header")
); .schema(new StringSchema());
return openApi ->
openApi
.getPaths()
.values()
.forEach(
pathItem ->
pathItem
.readOperations()
.forEach(operation -> operation.addParametersItem(lang)));
} }
} }

View File

@ -63,4 +63,6 @@ file:
ini.drawing.img.path: https://files.hanasys.jp/Drawing ini.drawing.img.path: https://files.hanasys.jp/Drawing
front: front:
url: http://1.248.227.176:3000 url: http://1.248.227.176:3000
swagger.url: http://localhost:38080

View File

@ -6,9 +6,11 @@ server:
spring: spring:
datasource: datasource:
driver-class-name: net.sf.log4jdbc.sql.jdbcapi.DriverSpy driver-class-name: net.sf.log4jdbc.sql.jdbcapi.DriverSpy
jdbc-url: jdbc:log4jdbc:sqlserver://1.248.227.176:1433;databaseName=NEWPVCAD;encrypt=true;trustServerCertificate=true #jdbc-url: jdbc:log4jdbc:sqlserver://1.248.227.176:1433;databaseName=NEWPVCAD;encrypt=true;trustServerCertificate=true
jdbc-url: jdbc:log4jdbc:sqlserver://192.168.200.220:1433;databaseName=NEWPVCAD;encrypt=false;trustServerCertificate=false
username: pvDBuser username: pvDBuser
password: ENC(W7owprYnvf7vqwO6Piw4dHfVBCSxE4Ck) #password: ENC(W7owprYnvf7vqwO6Piw4dHfVBCSxE4Ck)
password: ENC(Zc3J45rtPR/uQDeDOcrnF/iGLlU6U3y6)
maximum-pool-size: 4 maximum-pool-size: 4
pool-name: Master-HikariPool pool-name: Master-HikariPool
# datasource: # datasource:
@ -63,4 +65,6 @@ file:
ini.drawing.img.path: https://files.hanasys.jp/Drawing ini.drawing.img.path: https://files.hanasys.jp/Drawing
front: front:
url: http://1.248.227.176:3000 url: http://1.248.227.176:3000
swagger.url: https://dev-api.hanasys.jp

View File

@ -6,9 +6,10 @@ server:
spring: spring:
datasource: datasource:
driver-class-name: net.sf.log4jdbc.sql.jdbcapi.DriverSpy driver-class-name: net.sf.log4jdbc.sql.jdbcapi.DriverSpy
jdbc-url: jdbc:log4jdbc:sqlserver://1.248.227.176:1433;databaseName=NEWPVCAD;encrypt=true;trustServerCertificate=true #jdbc-url: jdbc:log4jdbc:sqlserver://1.248.227.176:1433;databaseName=NEWPVCAD;encrypt=true;trustServerCertificate=true
jdbc-url: jdbc:log4jdbc:sqlserver://192.168.200.220:1433;databaseName=NEWPVCAD;encrypt=false;trustServerCertificate=false
username: pvDBuser username: pvDBuser
password: ENC(W7owprYnvf7vqwO6Piw4dHfVBCSxE4Ck) password: ENC(Zc3J45rtPR/uQDeDOcrnF/iGLlU6U3y6)
maximum-pool-size: 4 maximum-pool-size: 4
pool-name: Master-HikariPool pool-name: Master-HikariPool
# datasource: # datasource:

View File

@ -63,4 +63,6 @@ file:
ini.drawing.img.path: https://files.hanasys.jp/Drawing ini.drawing.img.path: https://files.hanasys.jp/Drawing
front: front:
url: https://hanasys.jp url: https://hanasys.jp
swagger.url: https://api.hanasys.jp

View File

@ -82,3 +82,4 @@ springdoc:
swagger-ui: swagger-ui:
operations-sorter: alpha operations-sorter: alpha
swagger.url: http://localhost:8080