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