Skip to content

Commit

Permalink
[Feat] FAQ 조회 로직 구현 (#61)
Browse files Browse the repository at this point in the history
* [Feat] FAQ 삽입 로직 구현

* [Feat] FAQ 조회 로직 구현

* [Feat] FAQ 생성 로직 admin 그룹으로 변경
  • Loading branch information
iiqcov authored Sep 5, 2024
1 parent 912a409 commit b2469f8
Show file tree
Hide file tree
Showing 11 changed files with 187 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import appjjang.fitpet.domain.admin.application.AdminService;
import appjjang.fitpet.domain.admin.dto.request.AdminInsuranceRequest;
import appjjang.fitpet.domain.question.application.QuestionService;
import appjjang.fitpet.domain.question.dto.request.FaqCreateRequest;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
Expand All @@ -18,6 +20,7 @@
@RequestMapping("/admin")
public class AdminController {
private final AdminService adminservice;
private final QuestionService questionService;

@Operation(summary = "admin으로 체결된 보험 등록", description = "MY펫등록을 진행합니다.")
@PostMapping("/insurance")
Expand All @@ -26,4 +29,12 @@ public ResponseEntity<Void> registerInsurance(@RequestBody AdminInsuranceRequest
return ResponseEntity.status(HttpStatus.CREATED)
.build();
}

@Operation(summary = "FAQ 생성", description = "관리자가 FQA를 생성합니다.")
@PostMapping("/questions")
public ResponseEntity<Void> addQuestion(@RequestBody FaqCreateRequest request) {
questionService.addQuestion(request);
return ResponseEntity.status(HttpStatus.CREATED)
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@Tag(name = "관리자 API", description = "클라이언트에서는 사용되지 않습니다.")
@Tag(name = "admin API", description = "관리자 API 입니다.")
@RestController
@RequiredArgsConstructor
@RequestMapping("/admin")
Expand Down
17 changes: 17 additions & 0 deletions src/main/java/appjjang/fitpet/domain/question/FaqDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package appjjang.fitpet.domain.question;

import appjjang.fitpet.domain.question.domain.Question;
import lombok.Getter;

@Getter
public class FaqDto {
private String type;
private String question;
private String answer;

public FaqDto(Question question) {
this.type = question.getType();
this.question = question.getTitle();
this.answer = question.getAnswer();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package appjjang.fitpet.domain.question.api;

import appjjang.fitpet.domain.question.application.QuestionService;
import appjjang.fitpet.domain.question.dto.response.FaqQueryResponse;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;

import org.springframework.web.bind.annotation.*;

@Tag(name = "FAQ API", description = "FAQ 관련 API입니다.")
@RestController
@RequiredArgsConstructor
@RequestMapping("/questions")
public class QuestionController {
private final QuestionService questionService;

@Operation(summary = "FAQ 조회", description = "모든 FAQ를 조회합니다.")
@GetMapping
public FaqQueryResponse addQuestion(@RequestParam(required = false) String keyword) {
return questionService.getQuestionList(keyword);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package appjjang.fitpet.domain.question.application;

import appjjang.fitpet.domain.question.FaqDto;
import appjjang.fitpet.domain.question.dao.QuestionRepository;
import appjjang.fitpet.domain.question.domain.Question;
import appjjang.fitpet.domain.question.dto.request.FaqCreateRequest;
import appjjang.fitpet.domain.question.dto.response.FaqQueryResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
@Transactional
public class QuestionService {
private final QuestionRepository questionRepository;

public void addQuestion(FaqCreateRequest request) {
questionRepository.save(Question.createQuestion(request.getType(), request.getTitle(), request.getAnswer()));
}

@Transactional(readOnly = true)
public FaqQueryResponse getQuestionList(String keyword) {
List<String> types = questionRepository.findDistinctTypes();
List<FaqDto> dtoList = questionRepository.findQuestionByType(keyword).stream()
.map(FaqDto::new)
.collect(Collectors.toList());
return new FaqQueryResponse(types.size(), types, dtoList.size(), dtoList);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package appjjang.fitpet.domain.question.dao;

import appjjang.fitpet.domain.question.domain.Question;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface QuestionRepository extends JpaRepository<Question, Long> , QuestionRepositoryCustom{
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package appjjang.fitpet.domain.question.dao;

import appjjang.fitpet.domain.question.domain.Question;

import java.util.List;

public interface QuestionRepositoryCustom {
List<String> findDistinctTypes();
List<Question> findQuestionByType(String keyword);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package appjjang.fitpet.domain.question.dao;

import appjjang.fitpet.domain.question.domain.Question;
import com.querydsl.core.BooleanBuilder;
import com.querydsl.jpa.impl.JPAQueryFactory;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Repository;

import java.util.List;

import static appjjang.fitpet.domain.question.domain.QQuestion.question;

@Repository
@RequiredArgsConstructor
public class QuestionRepositoryImpl implements QuestionRepositoryCustom{
private final JPAQueryFactory queryFactory;

@Override
public List<String> findDistinctTypes() {
return queryFactory
.select(question.type)
.distinct()
.from(question)
.fetch();
}

@Override
public List<Question> findQuestionByType(String keyword) {
BooleanBuilder builder = new BooleanBuilder();
if (keyword != null) {
builder.and(question.type.eq(keyword));
}
return queryFactory.selectFrom(question)
.where(builder)
.fetch();
}
}
18 changes: 18 additions & 0 deletions src/main/java/appjjang/fitpet/domain/question/domain/Question.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import jakarta.persistence.*;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

Expand All @@ -16,5 +17,22 @@ public class Question {

private String type;
private String title;

@Column(length = 2000)
private String answer;

@Builder
private Question(String type, String title, String answer) {
this.type = type;
this.title = title;
this.answer = answer;
}

public static Question createQuestion(String type, String title, String answer) {
return Question.builder()
.type(type)
.title(title)
.answer(answer)
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package appjjang.fitpet.domain.question.dto.request;

import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@NoArgsConstructor
public class FaqCreateRequest {
private String type;
private String title;
private String answer;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package appjjang.fitpet.domain.question.dto.response;

import appjjang.fitpet.domain.question.FaqDto;
import lombok.AllArgsConstructor;
import lombok.Getter;

import java.util.List;

@Getter
@AllArgsConstructor
public class FaqQueryResponse {
private long typeCount;
private List<String> typeList;
private int questionCount;
private List<FaqDto> questionList;
}

0 comments on commit b2469f8

Please sign in to comment.