diff --git a/pav-server/src/main/java/com/palnet/biz/api/cns/qna/controller/CnsQnaController.java b/pav-server/src/main/java/com/palnet/biz/api/cns/qna/controller/CnsQnaController.java index ffc869ec..a5afd614 100644 --- a/pav-server/src/main/java/com/palnet/biz/api/cns/qna/controller/CnsQnaController.java +++ b/pav-server/src/main/java/com/palnet/biz/api/cns/qna/controller/CnsQnaController.java @@ -12,6 +12,7 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import com.palnet.biz.api.cns.qna.model.QnaBasModel; +import com.palnet.biz.api.cns.qna.model.QnaDetailRSModel; import com.palnet.biz.api.cns.qna.model.QnaInsertRQModel; import com.palnet.biz.api.cns.qna.model.QnaRSModel; import com.palnet.biz.api.cns.qna.model.QnaSelectListRQ; @@ -47,7 +48,7 @@ public class CnsQnaController { @GetMapping("/select") @Tag(name = "QNA", description = "QNA 관련 API") @ApiOperation(value = "QnA 리스트 조회") - public ResponseEntity selectQna(QnaSelectListRQ rq){ + public ResponseEntity> selectQna(QnaSelectListRQ rq){ log.warn("CnsFaqController - selectQna()"); List result = cnsQnaService.selectQnaList(rq); @@ -55,17 +56,18 @@ public class CnsQnaController { return ResponseEntity.ok().body(result); } - @GetMapping("/detail/{qnaSno}") + + @GetMapping("/{qnaSno}/detail") public ResponseEntity detailQna(@PathVariable int qnaSno){ log.warn("CnsFaqController - selectQna()"); log.warn("rq -> {}", qnaSno); + List reulst = cnsQnaService.getQnaDetail(qnaSno); - - return ResponseEntity.ok().body(null); + return ResponseEntity.ok().body(reulst); } - @PostMapping("/update") + @PostMapping("/{qnaSno}/update") public ResponseEntity updateQna(@RequestBody QnaInsertRQModel rq){ log.warn("CnsFaqController - updateQna()"); log.warn("rq -> {}", rq); @@ -74,7 +76,7 @@ public class CnsQnaController { return ResponseEntity.ok().body(null); } - @GetMapping("/delete") + @GetMapping("/{qnaSno}/delete") public ResponseEntity deleteQna(@RequestBody QnaBasModel rq){ log.warn("CnsFaqController - deleteQna()"); log.warn("rq -> {}", rq); diff --git a/pav-server/src/main/java/com/palnet/biz/api/cns/qna/model/QnaBasModel.java b/pav-server/src/main/java/com/palnet/biz/api/cns/qna/model/QnaBasModel.java index 907e69a2..945df598 100644 --- a/pav-server/src/main/java/com/palnet/biz/api/cns/qna/model/QnaBasModel.java +++ b/pav-server/src/main/java/com/palnet/biz/api/cns/qna/model/QnaBasModel.java @@ -15,7 +15,7 @@ public class QnaBasModel { private String title; - private String content; + private String content; private int fileGroupNo; diff --git a/pav-server/src/main/java/com/palnet/biz/api/cns/qna/model/QnaDetailRSModel.java b/pav-server/src/main/java/com/palnet/biz/api/cns/qna/model/QnaDetailRSModel.java new file mode 100644 index 00000000..c86bf5c3 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/cns/qna/model/QnaDetailRSModel.java @@ -0,0 +1,34 @@ +package com.palnet.biz.api.cns.qna.model; + +import java.time.Instant; +import java.util.List; + +import com.palnet.biz.jpa.entity.ComFileBas; + +import lombok.Data; + +@Data +public class QnaDetailRSModel { + + private int qnaSno; + + private int targetSno; + + private String category; + + private String title; + + private String content; + + private Integer viewCnt; + + private String createUserId; + + private Instant createDt; + + private String updateUserId; + + private Instant updateDt; + + private List files; +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/cns/qna/model/QnaInsertRQModel.java b/pav-server/src/main/java/com/palnet/biz/api/cns/qna/model/QnaInsertRQModel.java index 086f2bae..78f5d214 100644 --- a/pav-server/src/main/java/com/palnet/biz/api/cns/qna/model/QnaInsertRQModel.java +++ b/pav-server/src/main/java/com/palnet/biz/api/cns/qna/model/QnaInsertRQModel.java @@ -9,7 +9,7 @@ import lombok.Data; @Data public class QnaInsertRQModel { - private Integer targetSno; // 상위 파일 번호 + private Integer targetSno; // 상위 Qna 번호 private String category; diff --git a/pav-server/src/main/java/com/palnet/biz/api/cns/qna/model/QnaRQModel.java b/pav-server/src/main/java/com/palnet/biz/api/cns/qna/model/QnaRQModel.java deleted file mode 100644 index 1d6de86f..00000000 --- a/pav-server/src/main/java/com/palnet/biz/api/cns/qna/model/QnaRQModel.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.palnet.biz.api.cns.qna.model; - -import lombok.Data; - -@Data -public class QnaRQModel { - -} diff --git a/pav-server/src/main/java/com/palnet/biz/api/cns/qna/service/CnsQnaService.java b/pav-server/src/main/java/com/palnet/biz/api/cns/qna/service/CnsQnaService.java index e7f81453..be99fa7d 100644 --- a/pav-server/src/main/java/com/palnet/biz/api/cns/qna/service/CnsQnaService.java +++ b/pav-server/src/main/java/com/palnet/biz/api/cns/qna/service/CnsQnaService.java @@ -1,6 +1,7 @@ package com.palnet.biz.api.cns.qna.service; import java.time.Instant; +import java.util.ArrayList; import java.util.List; import javax.transaction.Transactional; @@ -10,12 +11,15 @@ import org.springframework.web.multipart.MultipartFile; import com.palnet.biz.api.acnt.jwt.utils.JwtTokenUtil; import com.palnet.biz.api.cns.qna.model.QnaBasModel; +import com.palnet.biz.api.cns.qna.model.QnaDetailRSModel; import com.palnet.biz.api.cns.qna.model.QnaInsertRQModel; import com.palnet.biz.api.cns.qna.model.QnaSelectListRQ; import com.palnet.biz.api.comn.file.service.ComnFileService; import com.palnet.biz.jpa.entity.CnsQnaBas; +import com.palnet.biz.jpa.entity.ComFileBas; import com.palnet.biz.jpa.repository.cns.CnsQnaBasRepository; import com.palnet.biz.jpa.repository.cns.CnsQnaQueryRepository; +import com.palnet.biz.jpa.repository.com.ComFileBasRepository; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -25,25 +29,80 @@ import lombok.extern.slf4j.Slf4j; @RequiredArgsConstructor public class CnsQnaService { - private final ComnFileService comnFileService; private final CnsQnaBasRepository cnsQnaBasRepository; private final CnsQnaQueryRepository cnsQnaQueryRepository; + private final ComFileBasRepository comFileBasRepository; + private final JwtTokenUtil jwtTokenUtil; - public List selectQnaList(QnaSelectListRQ rq){ - log.warn("CnsQnaService - selectQnaList()"); - log.warn("rq -> {}", rq); - List result = cnsQnaQueryRepository.getQnaList(rq.getCategory(), rq.getCategory()); + /** + * Qna 상세불러오기 + * @param qnaSno + * @return + */ + public List getQnaDetail(int qnaSno){ + + QnaBasModel qnaBasModel = cnsQnaQueryRepository.getQnaDetail(qnaSno).get(0); + List files = null; + if(qnaBasModel.getFileGroupNo() != 0) files = comFileBasRepository.findByFileGroupNo(qnaBasModel.getFileGroupNo()); + + QnaDetailRSModel node = new QnaDetailRSModel(); + node.setQnaSno(qnaSno); + node.setTargetSno(qnaBasModel.getTargetSno()); + node.setCategory(qnaBasModel.getCategory()); + node.setTitle(qnaBasModel.getTitle()); + node.setContent(qnaBasModel.getContent()); + node.setViewCnt(qnaBasModel.getViewCnt()); + node.setCreateUserId(qnaBasModel.getCreateUserId()); + node.setCreateDt(qnaBasModel.getCreateDt()); + node.setUpdateUserId(qnaBasModel.getUpdateUserId()); + node.setUpdateDt(qnaBasModel.getUpdateDt()); + node.setFiles(files); + + int targetSno = qnaSno; + + List result = new ArrayList<>(); + result.add(node); + + // 대댓글 불러오기 + while(true){ + + CnsQnaBas cnsQnaBas = cnsQnaBasRepository.findFirstByTargetSno(targetSno); + if(cnsQnaBas == null) break; + + QnaDetailRSModel detailNode = new QnaDetailRSModel(); + detailNode.setQnaSno(cnsQnaBas.getQnaSno()); + detailNode.setTargetSno(cnsQnaBas.getTargetSno()); + detailNode.setCategory(cnsQnaBas.getCategory()); + detailNode.setTitle(cnsQnaBas.getTitle()); + detailNode.setContent(cnsQnaBas.getContent()); + detailNode.setCreateUserId(cnsQnaBas.getCreateUserId()); + detailNode.setCreateDt(cnsQnaBas.getCreateDt()); + detailNode.setUpdateUserId(cnsQnaBas.getUpdateUserId()); + detailNode.setUpdateDt(cnsQnaBas.getUpdateDt()); + + result.add(detailNode); + + targetSno = cnsQnaBas.getQnaSno(); + } return result; - } - + } + /** + * Qna리스트 조회 + * @param rq + * @return + */ + public List selectQnaList(QnaSelectListRQ rq){ + + return cnsQnaQueryRepository.getQnaList(rq.getCategory(), rq.getCategory()); + } /** * QnaInsert @@ -53,8 +112,9 @@ public class CnsQnaService { @Transactional public boolean insertQna(QnaInsertRQModel rq){ - List files = rq.getFiles(); - int fileGroupNo = comnFileService.fileUpload(files); // File 업로드 + List files = rq.getFiles(); + Integer fileGroupNo = null; + if(files != null && files.size() > 0) fileGroupNo = comnFileService.fileUpload(files); // File 업로드 String userId = jwtTokenUtil.getUserIdByToken(); @@ -64,12 +124,13 @@ public class CnsQnaService { cnsQnaBas.setCategory(rq.getCategory()); cnsQnaBas.setTitle(rq.getTitle()); cnsQnaBas.setContent(rq.getContent()); - cnsQnaBas.setFileGroupNo(fileGroupNo); cnsQnaBas.setCreateDt(Instant.now()); cnsQnaBas.setCreateUserId(userId); cnsQnaBas.setUpdateDt(Instant.now()); cnsQnaBas.setUpdateUserId(userId); - + cnsQnaBas.setExpsrYn("Y"); + + if(fileGroupNo != null) cnsQnaBas.setFileGroupNo(fileGroupNo); if(rq.getTargetSno() != null) cnsQnaBas.setTargetSno(rq.getTargetSno()); cnsQnaBasRepository.save(cnsQnaBas); diff --git a/pav-server/src/main/java/com/palnet/biz/jpa/repository/cns/CnsQnaBasRepository.java b/pav-server/src/main/java/com/palnet/biz/jpa/repository/cns/CnsQnaBasRepository.java index d8406d9c..42b104d5 100644 --- a/pav-server/src/main/java/com/palnet/biz/jpa/repository/cns/CnsQnaBasRepository.java +++ b/pav-server/src/main/java/com/palnet/biz/jpa/repository/cns/CnsQnaBasRepository.java @@ -1,5 +1,9 @@ package com.palnet.biz.jpa.repository.cns; +import java.util.List; + +import javax.persistence.Id; + import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; @@ -8,4 +12,5 @@ import com.palnet.biz.jpa.entity.CnsQnaBas; @Repository public interface CnsQnaBasRepository extends JpaRepository{ + CnsQnaBas findFirstByTargetSno(int targetSno); } diff --git a/pav-server/src/main/java/com/palnet/biz/jpa/repository/cns/CnsQnaQueryRepository.java b/pav-server/src/main/java/com/palnet/biz/jpa/repository/cns/CnsQnaQueryRepository.java index 637a6a76..7d5b52cf 100644 --- a/pav-server/src/main/java/com/palnet/biz/jpa/repository/cns/CnsQnaQueryRepository.java +++ b/pav-server/src/main/java/com/palnet/biz/jpa/repository/cns/CnsQnaQueryRepository.java @@ -8,6 +8,8 @@ import com.palnet.biz.api.cns.faq.model.FaqListRSModel; import com.palnet.biz.api.cns.qna.model.QnaBasModel; import com.palnet.biz.jpa.entity.QCnsFaqBas; import com.palnet.biz.jpa.entity.QCnsQnaBas; +import com.palnet.comn.code.ErrorCode; +import com.palnet.comn.exception.CustomException; import com.querydsl.core.BooleanBuilder; import com.querydsl.core.types.Projections; import com.querydsl.jpa.impl.JPAQueryFactory; @@ -20,44 +22,92 @@ import lombok.extern.slf4j.Slf4j; @RequiredArgsConstructor public class CnsQnaQueryRepository { - private final JPAQueryFactory query; - - public List getQnaList(String category, String word) { - - QCnsQnaBas bas = QCnsQnaBas.cnsQnaBas; - - 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)); - } - - List r = query + private final JPAQueryFactory query; + + /** + * 카테고리와 글로 게시글 검색, 만약 조건 없으면 전체검색 + * @param category + * @param word + * @return + */ + public List getQnaList(String category, String word) { + QCnsQnaBas bas = QCnsQnaBas.cnsQnaBas; + + 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)); + } + + List r = query .select(Projections.bean( - QnaBasModel.class, - bas.qnaSno, - bas.category, - bas.title, - bas.content, - bas.fileGroupNo, - bas.viewCnt, - bas.expsrYn, - bas.delYn, - bas.createUserId, - bas.createDt, - bas.updateUserId, - bas.updateDt + QnaBasModel.class, + bas.qnaSno, + bas.category, + bas.title, + bas.content, + bas.fileGroupNo, + bas.viewCnt, + bas.expsrYn, + bas.delYn, + bas.createUserId, + bas.createDt, + bas.updateUserId, + bas.updateDt )) .from(bas) .where(builder) .fetch(); - - return r; - } + + return r; + } + + /** + * 첫 상세보기 검색, target번호가 있으면 안됨 + * @param qnaSno + * @return + */ + public List getQnaDetail(int qnaSno){ + + QCnsQnaBas qCnsQnaBas = QCnsQnaBas.cnsQnaBas; + + BooleanBuilder builder = new BooleanBuilder(); + builder.and(qCnsQnaBas.qnaSno.eq(qnaSno)); + builder.and(qCnsQnaBas.targetSno.eq(0)); + + List result = query.select( + Projections.bean( + QnaBasModel.class, + qCnsQnaBas.qnaSno, + qCnsQnaBas.targetSno, + qCnsQnaBas.category, + qCnsQnaBas.title, + qCnsQnaBas.content, + qCnsQnaBas.fileGroupNo, + qCnsQnaBas.viewCnt, + qCnsQnaBas.expsrYn, + qCnsQnaBas.delYn, + qCnsQnaBas.createUserId, + qCnsQnaBas.createDt, + qCnsQnaBas.updateUserId, + qCnsQnaBas.updateDt + )) + .from(qCnsQnaBas) + .where(builder) + .fetch(); + + log.warn("result -> {}", result); + + if(result == null || result.size() < 1) throw new CustomException(ErrorCode.NON_VALID_PARAMETER); + + return result; + } + + } diff --git a/pav-server/src/main/java/com/palnet/biz/jpa/repository/com/ComFileBasRepository.java b/pav-server/src/main/java/com/palnet/biz/jpa/repository/com/ComFileBasRepository.java index 0586623d..6cc4fb22 100644 --- a/pav-server/src/main/java/com/palnet/biz/jpa/repository/com/ComFileBasRepository.java +++ b/pav-server/src/main/java/com/palnet/biz/jpa/repository/com/ComFileBasRepository.java @@ -1,5 +1,7 @@ package com.palnet.biz.jpa.repository.com; +import java.util.List; + import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; @@ -11,4 +13,7 @@ public interface ComFileBasRepository extends JpaRepository ComFileBas findFirstByOrderByFileSnoDesc(); ComFileBas findFirstByOrderByFileGroupNoDesc(); + + List findByFileGroupNo(int fileGroupNo); + }