qkr7828
7 months ago
4 changed files with 818 additions and 0 deletions
@ -0,0 +1,165 @@ |
|||||||
|
package kr.co.palnet.kac.data.cns.repository; |
||||||
|
|
||||||
|
import com.querydsl.core.BooleanBuilder; |
||||||
|
import com.querydsl.core.types.Projections; |
||||||
|
import com.querydsl.jpa.impl.JPAQueryFactory; |
||||||
|
import kr.co.palnet.kac.data.cns.model.CnsFaqBas; |
||||||
|
import kr.co.palnet.kac.data.cns.model.QCnsFaqBas; |
||||||
|
import lombok.RequiredArgsConstructor; |
||||||
|
import lombok.extern.slf4j.Slf4j; |
||||||
|
import org.springframework.stereotype.Repository; |
||||||
|
|
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
@Slf4j |
||||||
|
@Repository |
||||||
|
@RequiredArgsConstructor |
||||||
|
public class CnsFaqQueryRepository { |
||||||
|
|
||||||
|
private final JPAQueryFactory query; |
||||||
|
/** |
||||||
|
* 조건값으로 FaQ리스트를 조회하는 SQL기능. |
||||||
|
* @param category |
||||||
|
* @param word |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public List<CnsFaqBas> getFaqList(String category, String word) { |
||||||
|
|
||||||
|
QCnsFaqBas bas = QCnsFaqBas.cnsFaqBas; |
||||||
|
|
||||||
|
BooleanBuilder builder = new BooleanBuilder(); |
||||||
|
builder.and(bas.delYn.eq("N")); |
||||||
|
builder.and(bas.expsrYn.eq("Y")); |
||||||
|
|
||||||
|
if (category != null) { |
||||||
|
builder.and(bas.category.eq(category)); |
||||||
|
} |
||||||
|
|
||||||
|
if (word != null) { |
||||||
|
builder.and(bas.title.contains(word)); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 삭제여부[delYn]값이 'N' 조건, |
||||||
|
* 표출여부[expsrYn]값이 'Y' 조건, |
||||||
|
* 카테고리값[category]값 조건, |
||||||
|
* 제목[title] 값이 word와의 조건 값으로 조회하는 SQL 입니다. |
||||||
|
* |
||||||
|
* SELECT |
||||||
|
* CFB.FAQ_SNO , |
||||||
|
* CFB.CATEGORY , |
||||||
|
* CFB.TITLE , |
||||||
|
* CFB.CONTENT , |
||||||
|
* CFB.VIEW_CNT , |
||||||
|
* CFB.EXPSR_YN , |
||||||
|
* CFB.CREATE_USER_ID , |
||||||
|
* CFB.CREATE_DT , |
||||||
|
* CFB.UPDATE_USER_ID , |
||||||
|
* CFB.UPDATE_DT |
||||||
|
* FROM CNS_FAQ_BAS CFB |
||||||
|
* WHERE CFB.DEL_YN = 'N' |
||||||
|
* AND CFB.EXPSR_YN = 'Y' |
||||||
|
* AND CFB.CATEGORY = #{category} |
||||||
|
* AND CFB.TITLE = #{word} |
||||||
|
* ORDER BY CFB.CREATE_DT DESC |
||||||
|
*/ |
||||||
|
List<CnsFaqBas> r = query |
||||||
|
.select(Projections.bean( |
||||||
|
CnsFaqBas.class, |
||||||
|
bas.faqSno, |
||||||
|
bas.category, |
||||||
|
bas.title, |
||||||
|
bas.content, |
||||||
|
bas.viewCnt, |
||||||
|
bas.expsrYn, |
||||||
|
bas.createUserId, |
||||||
|
bas.createDt, |
||||||
|
bas.updateUserId, |
||||||
|
bas.updateDt |
||||||
|
)) |
||||||
|
.from(bas) |
||||||
|
.where(builder) |
||||||
|
.orderBy(bas.createDt.desc()) |
||||||
|
.fetch(); |
||||||
|
|
||||||
|
|
||||||
|
return r; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 일련번호[sno]로 상세정보를 조회하는 SQL 기능. |
||||||
|
* @param sno |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public CnsFaqBas getFaqDetail(int sno) { |
||||||
|
|
||||||
|
QCnsFaqBas bas = QCnsFaqBas.cnsFaqBas; |
||||||
|
|
||||||
|
BooleanBuilder builder = new BooleanBuilder(); |
||||||
|
builder.and(bas.faqSno.eq((long) sno)); |
||||||
|
builder.and(bas.expsrYn.eq("Y")); |
||||||
|
builder.and(bas.delYn.eq("N")); |
||||||
|
|
||||||
|
/** |
||||||
|
* 일련번호[faqSno] 조건, |
||||||
|
* 표출여부[expsrYn]가 'Y' 인지 조건, |
||||||
|
* 삭제여부[delYn]가 'N' 인지 조건으로 조회하는 SQL 입니다. |
||||||
|
* |
||||||
|
* SELECT |
||||||
|
* CFB.FAQ_SNO , |
||||||
|
* CFB.CATEGORY , |
||||||
|
* CFB.TITLE , |
||||||
|
* CFB.CONTENT , |
||||||
|
* CFB.VIEW_CNT , |
||||||
|
* CFB.EXPSR_YN , |
||||||
|
* CFB.CREATE_USER_ID , |
||||||
|
* CFB.CREATE_DT , |
||||||
|
* CFB.UPDATE_USER_ID , |
||||||
|
* CFB.UPDATE_DT |
||||||
|
* FROM CNS_FAQ_BAS CFB |
||||||
|
* WHERE CFB.FAQ_SNO = #{sno} |
||||||
|
* AND CFB.EXPSR_YN = 'Y' |
||||||
|
* AND CFB.DEL_YN = 'N' |
||||||
|
*/ |
||||||
|
CnsFaqBas r = query |
||||||
|
.select(Projections.bean( |
||||||
|
CnsFaqBas.class, |
||||||
|
bas.faqSno, |
||||||
|
bas.category, |
||||||
|
bas.title, |
||||||
|
bas.content, |
||||||
|
bas.viewCnt, |
||||||
|
bas.expsrYn, |
||||||
|
bas.createUserId, |
||||||
|
bas.createDt, |
||||||
|
bas.updateUserId, |
||||||
|
bas.updateDt |
||||||
|
)) |
||||||
|
.from(bas) |
||||||
|
.where(builder) |
||||||
|
.fetchOne(); |
||||||
|
|
||||||
|
|
||||||
|
return r; |
||||||
|
} |
||||||
|
|
||||||
|
public void updateFaq(CnsFaqBas model) { |
||||||
|
QCnsFaqBas bas = QCnsFaqBas.cnsFaqBas; |
||||||
|
|
||||||
|
BooleanBuilder builder = new BooleanBuilder(); |
||||||
|
builder.and(bas.faqSno.eq(model.getFaqSno())); |
||||||
|
|
||||||
|
query.update(bas) |
||||||
|
.set(bas.category, model.getCategory()) |
||||||
|
.set(bas.title, model.getTitle()) |
||||||
|
.set(bas.content, model.getContent()) |
||||||
|
.set(bas.viewCnt, model.getViewCnt()) |
||||||
|
.set(bas.expsrYn, model.getExpsrYn()) |
||||||
|
.set(bas.updateUserId, model.getUpdateUserId()) |
||||||
|
.set(bas.updateDt, model.getUpdateDt()) |
||||||
|
.where(builder) |
||||||
|
.execute(); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,42 @@ |
|||||||
|
package kr.co.palnet.kac.data.cns.service; |
||||||
|
|
||||||
|
import kr.co.palnet.kac.data.cns.model.CnsFaqBas; |
||||||
|
import kr.co.palnet.kac.data.cns.repository.CnsFaqBasRepository; |
||||||
|
import kr.co.palnet.kac.data.cns.repository.CnsFaqQueryRepository; |
||||||
|
import lombok.RequiredArgsConstructor; |
||||||
|
import org.springframework.stereotype.Service; |
||||||
|
|
||||||
|
import java.util.List; |
||||||
|
import java.util.Optional; |
||||||
|
|
||||||
|
@Service |
||||||
|
@RequiredArgsConstructor |
||||||
|
public class CnsFaqDomainService { |
||||||
|
|
||||||
|
private final CnsFaqBasRepository cnsFaqBasRepository; |
||||||
|
private final CnsFaqQueryRepository query; |
||||||
|
|
||||||
|
public List<CnsFaqBas> getFaqList(String category, String word){ |
||||||
|
return query.getFaqList(category, word); |
||||||
|
} |
||||||
|
|
||||||
|
public void updateViewCnt(int sno){ |
||||||
|
cnsFaqBasRepository.updateViewCnt(sno); |
||||||
|
} |
||||||
|
|
||||||
|
public CnsFaqBas getFaqDetail(int sno){ |
||||||
|
return query.getFaqDetail(sno); |
||||||
|
} |
||||||
|
|
||||||
|
public CnsFaqBas saveFaqBas(CnsFaqBas cnsFaqBas){ |
||||||
|
return cnsFaqBasRepository.save(cnsFaqBas); |
||||||
|
} |
||||||
|
|
||||||
|
public Optional<CnsFaqBas> findById(int faqSno){ |
||||||
|
return cnsFaqBasRepository.findById(faqSno); |
||||||
|
} |
||||||
|
|
||||||
|
public int deleteFaq(int faqSno){ |
||||||
|
return cnsFaqBasRepository.deleteFaq(faqSno); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,392 @@ |
|||||||
|
package kr.co.palnet.kac.api.v1.cns.qna.controller; |
||||||
|
|
||||||
|
import com.palnet.biz.api.acnt.jwt.utils.JwtTokenUtil; |
||||||
|
import com.palnet.biz.api.cns.qna.model.*; |
||||||
|
import com.palnet.biz.api.cns.qna.service.CnsQnaService; |
||||||
|
import com.palnet.biz.api.comn.response.BasicResponse; |
||||||
|
import com.palnet.biz.api.comn.response.ErrorResponse; |
||||||
|
import com.palnet.biz.api.comn.response.SuccessResponse; |
||||||
|
import com.palnet.comn.code.RSErrorCode; |
||||||
|
import com.palnet.comn.exception.CustomException; |
||||||
|
import io.swagger.v3.oas.annotations.Operation; |
||||||
|
import io.swagger.v3.oas.annotations.Parameter; |
||||||
|
import io.swagger.v3.oas.annotations.enums.ParameterIn; |
||||||
|
import io.swagger.v3.oas.annotations.responses.ApiResponse; |
||||||
|
import io.swagger.v3.oas.annotations.responses.ApiResponses; |
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag; |
||||||
|
import lombok.RequiredArgsConstructor; |
||||||
|
import lombok.extern.slf4j.Slf4j; |
||||||
|
import org.springframework.http.HttpStatus; |
||||||
|
import org.springframework.http.ResponseEntity; |
||||||
|
import org.springframework.web.bind.annotation.*; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.HashMap; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Map; |
||||||
|
|
||||||
|
@Slf4j |
||||||
|
@RequiredArgsConstructor |
||||||
|
@RestController |
||||||
|
@Tag(name = "QNA", description = "QNA 관련 API") |
||||||
|
@RequestMapping("/api/cns/qna") |
||||||
|
public class CnsQnaController { |
||||||
|
|
||||||
|
private final CnsQnaService cnsQnaService; |
||||||
|
private final JwtTokenUtil jwtTokenUtil; |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* QnA 등록하는 기능, |
||||||
|
* QnaInsertRQModel 모델에 요청값으로 QnA를 등록하는 기능. |
||||||
|
* @param rq |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
@PostMapping(consumes = "multipart/form-data") |
||||||
|
@Operation(summary = "QNA 등록 (사용자)", description = "사용자 권한으로 QNA를 등록하는 API 입니다.") |
||||||
|
@ApiResponses(value = { |
||||||
|
@ApiResponse(responseCode = "200", description = "성공", |
||||||
|
content = { |
||||||
|
@io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", |
||||||
|
array = @io.swagger.v3.oas.annotations.media.ArraySchema( |
||||||
|
schema = @io.swagger.v3.oas.annotations.media.Schema(implementation = boolean.class))) |
||||||
|
}) |
||||||
|
}) |
||||||
|
public ResponseEntity<? extends BasicResponse> insertQna(QnaInsertRQModel rq) { |
||||||
|
boolean result = false; |
||||||
|
try { |
||||||
|
result = cnsQnaService.insertQna(rq); // Qna 추가 하는기능
|
||||||
|
} catch (CustomException e) { |
||||||
|
/** |
||||||
|
* try{ |
||||||
|
... |
||||||
|
} |
||||||
|
* try 영역 안 코드들중 문제가 생기면 오는 곳. |
||||||
|
* CustomException은 개발자가 "의도적으로" 낸 예외처리, |
||||||
|
* log.error 로그로 원인 파악과 함께 API를 호출한 곳에 서버에러 내려줌 |
||||||
|
*/ |
||||||
|
Map<String, Object> resultMap = new HashMap<>(); |
||||||
|
log.error("IGNORE : ", e); |
||||||
|
resultMap.put("result", false); |
||||||
|
resultMap.put("errorCode", e.getErrorCode()); |
||||||
|
resultMap.put("errorMessage", e.getMessage()); |
||||||
|
return ResponseEntity.ok().body(new SuccessResponse<>(resultMap)); |
||||||
|
} catch (Exception e) { |
||||||
|
/** |
||||||
|
* try{ |
||||||
|
... |
||||||
|
} |
||||||
|
* try 영역 안 코드들중 문제가 생기면 오는 곳. |
||||||
|
* log.error 로그로 원인 파악과 함께 API를 호출한 곳에 서버에러 내려줌 |
||||||
|
*/ |
||||||
|
log.error("IGNORE : ", e); |
||||||
|
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) |
||||||
|
.body(new ErrorResponse("Server Error", "-1")); |
||||||
|
|
||||||
|
} |
||||||
|
return ResponseEntity.ok().body(new SuccessResponse<>(result)); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* QnA리스트 조회하는 기능[관리자], |
||||||
|
* QnaListAdminRQ 조건값에 따라 조회함. |
||||||
|
* @param rq |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
@GetMapping |
||||||
|
@Operation(summary = "QNA 리스트 조회 (관리자)", description = "QNA 리스트를 관리자 권한으로 조회하는 API 입니다.") |
||||||
|
@ApiResponses(value = { |
||||||
|
@ApiResponse(responseCode = "200", description = "성공", |
||||||
|
content = { |
||||||
|
@io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", |
||||||
|
array = @io.swagger.v3.oas.annotations.media.ArraySchema( |
||||||
|
schema = @io.swagger.v3.oas.annotations.media.Schema(implementation = QnaBasModel.class))) |
||||||
|
}) |
||||||
|
}) |
||||||
|
public ResponseEntity<? extends BasicResponse> selectQna(QnaListAdminRQ rq) { |
||||||
|
|
||||||
|
List<QnaBasModel> result = new ArrayList<>(); |
||||||
|
try { |
||||||
|
result = cnsQnaService.selectQnaList(rq); // Qna리스트 조회하는 기능
|
||||||
|
} catch (CustomException e) { |
||||||
|
/** |
||||||
|
* try{ |
||||||
|
... |
||||||
|
} |
||||||
|
* try 영역 안 코드들중 문제가 생기면 오는 곳. |
||||||
|
* CustomException은 개발자가 "의도적으로" 낸 예외처리, |
||||||
|
* log.error 로그로 원인 파악과 함께 API를 호출한 곳에 서버에러 내려줌 |
||||||
|
*/ |
||||||
|
Map<String, Object> resultMap = new HashMap<>(); |
||||||
|
log.error("IGNORE : ", e); |
||||||
|
resultMap.put("result", false); |
||||||
|
resultMap.put("errorCode", e.getErrorCode()); |
||||||
|
resultMap.put("errorMessage", e.getMessage()); |
||||||
|
return ResponseEntity.ok().body(new SuccessResponse<>(resultMap)); |
||||||
|
} catch (Exception e) { |
||||||
|
/** |
||||||
|
* try{ |
||||||
|
... |
||||||
|
} |
||||||
|
* try 영역 안 코드들중 문제가 생기면 오는 곳. |
||||||
|
* log.error 로그로 원인 파악과 함께 API를 호출한 곳에 서버에러 내려줌 |
||||||
|
*/ |
||||||
|
log.error("IGNORE : ", e); |
||||||
|
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) |
||||||
|
.body(new ErrorResponse("Server Error", "-1")); |
||||||
|
|
||||||
|
} |
||||||
|
return ResponseEntity.ok().body(new SuccessResponse<>(result)); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* QnA리스트 조회하는 기능[관리자], |
||||||
|
* QnaSelectListRQ 값에 따라서 조회함. |
||||||
|
* @param rq |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
@GetMapping("/user") |
||||||
|
@Operation(summary = "QNA 리스트 조회 (사용자)", description = "QNA 리스트를 사용자 권한으로 조회하는 API 입니다.") |
||||||
|
@ApiResponses(value = { |
||||||
|
@ApiResponse(responseCode = "200", description = "성공", |
||||||
|
content = { |
||||||
|
@io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", |
||||||
|
array = @io.swagger.v3.oas.annotations.media.ArraySchema( |
||||||
|
schema = @io.swagger.v3.oas.annotations.media.Schema(implementation = QnaBasModel.class))) |
||||||
|
}) |
||||||
|
}) |
||||||
|
public ResponseEntity<? extends BasicResponse> selectQnaForUser(QnaSelectListRQ rq) { |
||||||
|
|
||||||
|
List<QnaBasModel> result = new ArrayList<>(); |
||||||
|
try { |
||||||
|
result = cnsQnaService.selectQnaForUser(rq); |
||||||
|
} catch (CustomException e) { |
||||||
|
/** |
||||||
|
* try{ |
||||||
|
... |
||||||
|
} |
||||||
|
* try 영역 안 코드들중 문제가 생기면 오는 곳. |
||||||
|
* CustomException은 개발자가 "의도적으로" 낸 예외처리, |
||||||
|
* log.error 로그로 원인 파악과 함께 API를 호출한 곳에 서버에러 내려줌 |
||||||
|
*/ |
||||||
|
Map<String, Object> resultMap = new HashMap<>(); |
||||||
|
log.error("IGNORE : ", e); |
||||||
|
resultMap.put("result", false); |
||||||
|
resultMap.put("errorCode", e.getErrorCode()); |
||||||
|
resultMap.put("errorMessage", e.getMessage()); |
||||||
|
return ResponseEntity.ok().body(new SuccessResponse<>(resultMap)); |
||||||
|
} catch (Exception e) { |
||||||
|
/** |
||||||
|
* try{ |
||||||
|
... |
||||||
|
} |
||||||
|
* try 영역 안 코드들중 문제가 생기면 오는 곳. |
||||||
|
* log.error 로그로 원인 파악과 함께 API를 호출한 곳에 서버에러 내려줌 |
||||||
|
*/ |
||||||
|
log.error("IGNORE : ", e); |
||||||
|
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) |
||||||
|
.body(new ErrorResponse("Server Error", "-1")); |
||||||
|
|
||||||
|
} |
||||||
|
return ResponseEntity.ok().body(new SuccessResponse<>(result)); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* QnA 상세보기 기능, |
||||||
|
* QnA일련번호[qnaSno]값으로 조회함. |
||||||
|
* @param qnaSno |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
@GetMapping("/{qnaSno}") |
||||||
|
@Operation(summary = "QNA 리스트 상세 조회", description = "QNA 리스트를 상세하게 조회하는 API 입니다.") |
||||||
|
public ResponseEntity<? extends BasicResponse> detailQna(@Parameter(name="qnaSno", description = "QnA일련번호", in = ParameterIn.PATH, example = "295") @PathVariable int qnaSno) { |
||||||
|
QnaDetailRSModel result = null; |
||||||
|
try { |
||||||
|
result = cnsQnaService.getQnaDetail(qnaSno); // Qna 상세불러오기 기능
|
||||||
|
} catch (CustomException e) { |
||||||
|
/** |
||||||
|
* try{ |
||||||
|
... |
||||||
|
} |
||||||
|
* try 영역 안 코드들중 문제가 생기면 오는 곳. |
||||||
|
* CustomException은 개발자가 "의도적으로" 낸 예외처리, |
||||||
|
* log.error 로그로 원인 파악과 함께 API를 호출한 곳에 서버에러 내려줌 |
||||||
|
*/ |
||||||
|
Map<String, Object> resultMap = new HashMap<>(); |
||||||
|
log.error("IGNORE : ", e); |
||||||
|
resultMap.put("result", false); |
||||||
|
resultMap.put("errorCode", e.getErrorCode()); |
||||||
|
resultMap.put("errorMessage", e.getMessage()); |
||||||
|
return ResponseEntity.ok().body(new SuccessResponse<>(resultMap)); |
||||||
|
} catch (Exception e) { |
||||||
|
/** |
||||||
|
* try{ |
||||||
|
... |
||||||
|
} |
||||||
|
* try 영역 안 코드들중 문제가 생기면 오는 곳. |
||||||
|
* log.error 로그로 원인 파악과 함께 API를 호출한 곳에 서버에러 내려줌 |
||||||
|
*/ |
||||||
|
log.error("IGNORE : ", e); |
||||||
|
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) |
||||||
|
.body(new ErrorResponse("Server Error", "-1")); |
||||||
|
|
||||||
|
} |
||||||
|
return ResponseEntity.ok().body(new SuccessResponse<>(result)); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* QnA수정 하는 기능[사용자], |
||||||
|
* QnaInsertRQModel 모델에 입력받은 사항들을 수정함. |
||||||
|
* @param rq |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
@PutMapping(consumes = "multipart/form-data") |
||||||
|
@Operation(summary = "QNA 수정 (사용자)", description = "QNA를 사용자 권한으로 수정하는 API 입니다.") |
||||||
|
@ApiResponses(value = { |
||||||
|
@ApiResponse(responseCode = "200", description = "성공", |
||||||
|
content = { |
||||||
|
@io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", |
||||||
|
array = @io.swagger.v3.oas.annotations.media.ArraySchema( |
||||||
|
schema = @io.swagger.v3.oas.annotations.media.Schema(implementation = boolean.class))) |
||||||
|
}) |
||||||
|
}) |
||||||
|
public ResponseEntity<? extends BasicResponse> updateQna(QnaInsertRQModel rq) { |
||||||
|
boolean result = false; |
||||||
|
try { |
||||||
|
result = cnsQnaService.updateQna(rq); // Qna 업데이트하는 기능
|
||||||
|
} catch (CustomException e) { |
||||||
|
/** |
||||||
|
* try{ |
||||||
|
... |
||||||
|
} |
||||||
|
* try 영역 안 코드들중 문제가 생기면 오는 곳. |
||||||
|
* CustomException은 개발자가 "의도적으로" 낸 예외처리, |
||||||
|
* log.error 로그로 원인 파악과 함께 API를 호출한 곳에 서버에러 내려줌 |
||||||
|
*/ |
||||||
|
Map<String, Object> resultMap = new HashMap<>(); |
||||||
|
log.error("IGNORE : ", e); |
||||||
|
resultMap.put("result", false); |
||||||
|
resultMap.put("errorCode", e.getErrorCode()); |
||||||
|
resultMap.put("errorMessage", e.getMessage()); |
||||||
|
return ResponseEntity.ok().body(new SuccessResponse<>(resultMap)); |
||||||
|
} catch (Exception e) { |
||||||
|
/** |
||||||
|
* try{ |
||||||
|
... |
||||||
|
} |
||||||
|
* try 영역 안 코드들중 문제가 생기면 오는 곳. |
||||||
|
* log.error 로그로 원인 파악과 함께 API를 호출한 곳에 서버에러 내려줌 |
||||||
|
*/ |
||||||
|
log.error("IGNORE : ", e); |
||||||
|
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) |
||||||
|
.body(new ErrorResponse("Server Error", "-1")); |
||||||
|
|
||||||
|
} |
||||||
|
return ResponseEntity.ok().body(new SuccessResponse<>(result)); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* QnA삭제하는 기능, |
||||||
|
* QnA일련번호[qnaSno]로 삭제함. |
||||||
|
* @param qnaSno |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
@DeleteMapping("/{qnaSno}") |
||||||
|
@Operation(summary = "QNA 삭제", description = "QNA를 삭제하는 API 입니다.") |
||||||
|
public ResponseEntity<? extends BasicResponse> deleteQna(@Parameter(name="qnaSno", description = "QnA일련번호", in = ParameterIn.PATH, example = "17") @PathVariable int qnaSno) { |
||||||
|
// TODO 관리자만 삭제 가능 여부인지 확인 필요
|
||||||
|
boolean result = false; |
||||||
|
try { |
||||||
|
result = cnsQnaService.deleteQna(qnaSno); // Qna 삭제하기, file들도 모두 논리삭제하는 기능.
|
||||||
|
} catch (CustomException e) { |
||||||
|
/** |
||||||
|
* try{ |
||||||
|
... |
||||||
|
} |
||||||
|
* try 영역 안 코드들중 문제가 생기면 오는 곳. |
||||||
|
* CustomException은 개발자가 "의도적으로" 낸 예외처리, |
||||||
|
* log.error 로그로 원인 파악과 함께 API를 호출한 곳에 서버에러 내려줌 |
||||||
|
*/ |
||||||
|
Map<String, Object> resultMap = new HashMap<>(); |
||||||
|
log.error("IGNORE : ", e); |
||||||
|
resultMap.put("result", false); |
||||||
|
resultMap.put("errorCode", e.getErrorCode()); |
||||||
|
resultMap.put("errorMessage", e.getMessage()); |
||||||
|
return ResponseEntity.ok().body(new SuccessResponse<>(resultMap)); |
||||||
|
} catch (Exception e) { |
||||||
|
/** |
||||||
|
* try{ |
||||||
|
... |
||||||
|
} |
||||||
|
* try 영역 안 코드들중 문제가 생기면 오는 곳. |
||||||
|
* log.error 로그로 원인 파악과 함께 API를 호출한 곳에 서버에러 내려줌 |
||||||
|
*/ |
||||||
|
log.error("IGNORE : ", e); |
||||||
|
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) |
||||||
|
.body(new ErrorResponse("Server Error", "-1")); |
||||||
|
|
||||||
|
} |
||||||
|
return ResponseEntity.ok().body(new SuccessResponse<>(result)); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* QnA 답변등록하는 기능[관리자], |
||||||
|
* QnaInsertAnserRQModel에 입력받은 값으로 답변을 등록함. |
||||||
|
* @param rq |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
@PutMapping("/answer") |
||||||
|
@Operation(summary = "QNA 답변 등록(관리자)", description = "QNA에 대한 답변을 관리자 권한으로 등록하는 API 입니다.") |
||||||
|
@ApiResponses(value = { |
||||||
|
@ApiResponse(responseCode = "200", description = "성공", |
||||||
|
content = { |
||||||
|
@io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", |
||||||
|
array = @io.swagger.v3.oas.annotations.media.ArraySchema( |
||||||
|
schema = @io.swagger.v3.oas.annotations.media.Schema(implementation = boolean.class))) |
||||||
|
}) |
||||||
|
}) |
||||||
|
public ResponseEntity<? extends BasicResponse> insertAnswer(@RequestBody QnaInsertAnserRQModel rq) { |
||||||
|
// TODO 추후 auth -> role 체크로 변경
|
||||||
|
boolean result = false; |
||||||
|
try { |
||||||
|
String userAuthByToken = jwtTokenUtil.getUserAuthByToken(); |
||||||
|
if (!"SUPER".equals(userAuthByToken)) { |
||||||
|
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(new ErrorResponse(RSErrorCode.AUTH_ERROR)); |
||||||
|
} |
||||||
|
|
||||||
|
result = cnsQnaService.insertAnswer(rq); // 답변추가하는 기능.
|
||||||
|
} catch (CustomException e) { |
||||||
|
/** |
||||||
|
* try{ |
||||||
|
... |
||||||
|
} |
||||||
|
* try 영역 안 코드들중 문제가 생기면 오는 곳. |
||||||
|
* CustomException은 개발자가 "의도적으로" 낸 예외처리, |
||||||
|
* log.error 로그로 원인 파악과 함께 API를 호출한 곳에 서버에러 내려줌 |
||||||
|
*/ |
||||||
|
Map<String, Object> resultMap = new HashMap<>(); |
||||||
|
log.error("IGNORE : ", e); |
||||||
|
resultMap.put("result", false); |
||||||
|
resultMap.put("errorCode", e.getErrorCode()); |
||||||
|
resultMap.put("errorMessage", e.getMessage()); |
||||||
|
return ResponseEntity.ok().body(new SuccessResponse<>(resultMap)); |
||||||
|
} catch (Exception e) { |
||||||
|
/** |
||||||
|
* try{ |
||||||
|
... |
||||||
|
} |
||||||
|
* try 영역 안 코드들중 문제가 생기면 오는 곳. |
||||||
|
* log.error 로그로 원인 파악과 함께 API를 호출한 곳에 서버에러 내려줌 |
||||||
|
*/ |
||||||
|
log.error("IGNORE : ", e); |
||||||
|
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) |
||||||
|
.body(new ErrorResponse("Server Error", "-1")); |
||||||
|
|
||||||
|
} |
||||||
|
return ResponseEntity.ok().body(new SuccessResponse<>(result)); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,219 @@ |
|||||||
|
package kr.co.palnet.kac.api.v1.cns.qna.service; |
||||||
|
|
||||||
|
import com.palnet.biz.api.acnt.jwt.utils.JwtTokenUtil; |
||||||
|
import com.palnet.biz.api.cns.qna.model.*; |
||||||
|
import com.palnet.biz.api.comn.file.model.ComnFileModel; |
||||||
|
import com.palnet.biz.api.comn.file.service.ComnFileService; |
||||||
|
import com.palnet.biz.jpa.entity.CnsQnaBas; |
||||||
|
import com.palnet.biz.jpa.entity.PtyCstmrBas; |
||||||
|
import com.palnet.biz.jpa.entity.PtyCstmrDtl; |
||||||
|
import com.palnet.biz.jpa.repository.cns.CnsQnaBasRepository; |
||||||
|
import com.palnet.biz.jpa.repository.cns.CnsQnaQueryRepository; |
||||||
|
import com.palnet.biz.jpa.repository.pty.PtyCstmrBasRepository; |
||||||
|
import com.palnet.biz.jpa.repository.pty.PtyCstmrDtlRepository; |
||||||
|
import com.palnet.comn.code.ErrorCode; |
||||||
|
import com.palnet.comn.exception.CustomException; |
||||||
|
import lombok.RequiredArgsConstructor; |
||||||
|
import lombok.extern.slf4j.Slf4j; |
||||||
|
import org.springframework.stereotype.Service; |
||||||
|
import org.springframework.web.multipart.MultipartFile; |
||||||
|
|
||||||
|
import javax.transaction.Transactional; |
||||||
|
import java.time.Instant; |
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.List; |
||||||
|
import java.util.stream.Collectors; |
||||||
|
|
||||||
|
@Service |
||||||
|
@Slf4j |
||||||
|
@RequiredArgsConstructor |
||||||
|
public class CnsQnaService { |
||||||
|
|
||||||
|
private final CnsQnaBasRepository cnsQnaBasRepository; |
||||||
|
|
||||||
|
private final CnsQnaQueryRepository cnsQnaQueryRepository; |
||||||
|
private final PtyCstmrBasRepository ptyCstmrBasRepository; |
||||||
|
private final PtyCstmrDtlRepository ptyCstmrDtlRepository; |
||||||
|
|
||||||
|
private final ComnFileService comnFileService; |
||||||
|
|
||||||
|
private final JwtTokenUtil jwtTokenUtil; |
||||||
|
|
||||||
|
/** |
||||||
|
* Qna 삭제하기, file들도 모두 논리삭제하는 기능. |
||||||
|
* @param qnaSno |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
// @Transactional는 데이터베이스의 정합성을 위해 사용합니다, 추가 수정 삭제 등에서 사용합니다, 이 기능에서는 삭제컬럼은 수정했기 때문에 사용했습니다.
|
||||||
|
@Transactional |
||||||
|
public boolean deleteQna(int qnaSno) { |
||||||
|
|
||||||
|
CnsQnaBas entity = cnsQnaBasRepository.findByQnaSnoAndDelYnAndExpsrYn(qnaSno, "N", "Y"); |
||||||
|
if (entity == null) throw new CustomException(ErrorCode.DATA_NOTFIND); |
||||||
|
|
||||||
|
if (entity.getFileGroupNo() != null) comnFileService.deleteFilesByFileGroupNo(entity.getFileGroupNo()); |
||||||
|
|
||||||
|
entity.setDelYn("Y"); |
||||||
|
|
||||||
|
cnsQnaBasRepository.save(entity); |
||||||
|
|
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Qna 업데이트하는 기능. |
||||||
|
* @param rq |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
// @Transactional는 데이터베이스의 정합성을 위해 사용합니다, 추가 수정 삭제 등에서 사용합니다, 이 기능에서는 수정하기 때문에 사용합니다.
|
||||||
|
@Transactional |
||||||
|
public boolean updateQna(QnaInsertRQModel rq) { |
||||||
|
|
||||||
|
CnsQnaBas entity = cnsQnaBasRepository.findFirstByQnaSnoAndTargetSnoAndDelYnAndExpsrYn(rq.getQnaSno(), 0, "N", "Y"); |
||||||
|
if (entity == null) throw new CustomException(ErrorCode.DATA_NOTFIND); |
||||||
|
|
||||||
|
// 파일 삭제(논리적 삭제)
|
||||||
|
List<Integer> prevFileSnoList = new ArrayList<>(); |
||||||
|
List<Integer> currentFileSnoList = new ArrayList<>(); |
||||||
|
if (entity.getFileGroupNo() != null) { |
||||||
|
List<ComnFileModel> prevFileInfos = comnFileService.getNormalFileListByGroupNo(entity.getFileGroupNo()); // 파일그룹번호[fileGroupNo]에 해당하는 파일등 모두 가져오는 기능.
|
||||||
|
prevFileSnoList = prevFileInfos.stream().map(ComnFileModel::getFileSno).collect(Collectors.toList()); |
||||||
|
} |
||||||
|
if (rq.getFileInfos() != null) { |
||||||
|
currentFileSnoList = rq.getFileInfos().stream().map(ComnFileModel::getFileSno).collect(Collectors.toList()); |
||||||
|
} |
||||||
|
|
||||||
|
boolean isChange = prevFileSnoList.removeAll(currentFileSnoList); |
||||||
|
if (isChange) { |
||||||
|
comnFileService.deleteFiles(prevFileSnoList); // File 삭제
|
||||||
|
} |
||||||
|
|
||||||
|
List<MultipartFile> files = rq.getFiles(); |
||||||
|
if (files != null && !files.isEmpty()) comnFileService.fileUpload(files, entity.getFileGroupNo()); // File 업로드
|
||||||
|
|
||||||
|
// if(rq.getCategory() != null) entity.setCategory(rq.getCategory());
|
||||||
|
// if(rq.getContent() != null) entity.setContent(rq.getContent());
|
||||||
|
// if(rq.getTitle() != null) entity.setTitle(rq.getTitle());
|
||||||
|
|
||||||
|
CnsQnaMapper.MAPPER.merge(entity, rq); |
||||||
|
|
||||||
|
String userId = jwtTokenUtil.getUserIdByToken(); |
||||||
|
|
||||||
|
if (userId == null) userId = "NONE"; |
||||||
|
|
||||||
|
entity.setUpdateUserId(userId); |
||||||
|
// 수정시 답변상태 미응답 상태로 변경
|
||||||
|
entity.setAnserStatus("N"); |
||||||
|
|
||||||
|
cnsQnaBasRepository.save(entity); |
||||||
|
|
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Qna 상세불러오기 기능. |
||||||
|
* @param qnaSno |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
// @Transactional는 데이터베이스의 정합성을 위해 사용합니다, 추가 수정 삭제 등에서 사용합니다, 이 기능에서는 조회수 증가하기 떄문에 사용했습니다.
|
||||||
|
@Transactional |
||||||
|
public QnaDetailRSModel getQnaDetail(int qnaSno) { |
||||||
|
|
||||||
|
cnsQnaBasRepository.pulsViewCount(qnaSno); |
||||||
|
|
||||||
|
CnsQnaBas entity = cnsQnaBasRepository.findFirstByQnaSnoAndTargetSnoAndDelYnAndExpsrYn(qnaSno, 0, "N", "Y"); |
||||||
|
if(entity == null) throw new CustomException(ErrorCode.DATA_NO); |
||||||
|
|
||||||
|
List<ComnFileModel> files = null; |
||||||
|
if (entity.getFileGroupNo() != null && entity.getFileGroupNo() != 0) |
||||||
|
files = comnFileService.getNormalFileListByGroupNo(entity.getFileGroupNo()); // 파일그룹번호[fileGroupNo]에 해당하는 파일등 모두 가져오는 기능.
|
||||||
|
|
||||||
|
QnaDetailRSModel model = CnsQnaMapper.MAPPER.toModel(entity); |
||||||
|
PtyCstmrBas user = ptyCstmrBasRepository.findByUserId(entity.getCreateUserId()).orElse(null); |
||||||
|
if (user != null) { |
||||||
|
PtyCstmrDtl ptyCstmrDtl = ptyCstmrDtlRepository.findById(user.getCstmrSno()).orElse(null); |
||||||
|
if (ptyCstmrDtl != null) model.setCreateUserNm(ptyCstmrDtl.getMemberName()); |
||||||
|
} |
||||||
|
|
||||||
|
model.setFileInfos(files); |
||||||
|
|
||||||
|
|
||||||
|
return model; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Qna리스트 조회하는 기능[관리자]. |
||||||
|
* |
||||||
|
* @param rq |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public List<QnaBasModel> selectQnaList(QnaListAdminRQ rq) { |
||||||
|
return cnsQnaQueryRepository.getQnaList(rq); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Qna리스트 조회하는 기능[유저] |
||||||
|
* @param rq |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public List<QnaBasModel> selectQnaForUser(QnaSelectListRQ rq) { |
||||||
|
String userId = jwtTokenUtil.getUserIdByToken(); |
||||||
|
return cnsQnaQueryRepository.getQnaListForUser(rq, userId); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Qna 추가 하는기능. |
||||||
|
* @param rq |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
@Transactional |
||||||
|
public boolean insertQna(QnaInsertRQModel rq) { |
||||||
|
|
||||||
|
List<MultipartFile> files = rq.getFiles(); |
||||||
|
Integer fileGroupNo = null; |
||||||
|
if (files != null && files.size() > 0) fileGroupNo = comnFileService.fileUpload(files, null); // File 업로드
|
||||||
|
|
||||||
|
String userId = jwtTokenUtil.getUserIdByToken(); |
||||||
|
|
||||||
|
if (userId == null) userId = "NONE"; |
||||||
|
|
||||||
|
CnsQnaBas cnsQnaBas = CnsQnaMapper.MAPPER.toEntity(rq); |
||||||
|
cnsQnaBas.setCreateUserId(userId); |
||||||
|
cnsQnaBas.setUpdateUserId(userId); |
||||||
|
cnsQnaBas.setExpsrYn("Y"); |
||||||
|
cnsQnaBas.setDelYn("N"); |
||||||
|
cnsQnaBas.setViewCnt(0); |
||||||
|
cnsQnaBas.setAnserStatus("N"); |
||||||
|
|
||||||
|
if (fileGroupNo != null) cnsQnaBas.setFileGroupNo(fileGroupNo); |
||||||
|
|
||||||
|
cnsQnaBasRepository.save(cnsQnaBas); |
||||||
|
|
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* 답변추가하는 기능. |
||||||
|
* @param rq |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public boolean insertAnswer(QnaInsertAnserRQModel rq) { |
||||||
|
CnsQnaBas entity = cnsQnaBasRepository.findByQnaSnoAndDelYnAndExpsrYn(rq.getQnaSno(), "N", "Y"); |
||||||
|
if (entity == null) throw new CustomException(ErrorCode.DATA_NOTFIND); |
||||||
|
|
||||||
|
String userId = jwtTokenUtil.getUserIdByToken(); |
||||||
|
String userNm = jwtTokenUtil.getUserNmByToken(); |
||||||
|
|
||||||
|
CnsQnaMapper.MAPPER.merge(entity, rq); |
||||||
|
entity.setUpdateUserId(userId); |
||||||
|
entity.setAnserUserNm(userNm); |
||||||
|
entity.setAnserProcDt(Instant.now()); |
||||||
|
entity.setAnserStatus("Y".equals(rq.getAnserStatus()) ? "Y" : "N"); |
||||||
|
|
||||||
|
cnsQnaBasRepository.save(entity); |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
} |
Loading…
Reference in new issue