Skip to content

Commit

Permalink
feat: #186 csv 이용 질문 일괄 삽입 기능 추가
Browse files Browse the repository at this point in the history
  • Loading branch information
jaewonLeeKOR committed Sep 26, 2024
1 parent 5b8940c commit 2074dcf
Show file tree
Hide file tree
Showing 7 changed files with 53 additions and 30 deletions.
2 changes: 2 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ dependencies {
// actuator
implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'io.micrometer:micrometer-registry-prometheus'
// open csv
implementation 'com.opencsv:opencsv:5.5.1'
}

dependencyManagement {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,8 @@
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 java.util.UUID;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;

@Tag(name = "관리자 질문 API", description = "관리자 질문 관련 API")
@RestController
Expand All @@ -27,23 +20,28 @@ public class AdminQuestionController {

@Operation(summary = "질문 추가 API", description = "질문을 추가합니다. content를 입력하세요")
@ApiResponses(value = {
@ApiResponse(responseCode = "COMMON200", description = "성공"),
@ApiResponse(responseCode = "COMMON200", description = "성공"),
})
@PostMapping
public BaseResponse<QuestionId> createQuestion(
@RequestBody QuestionCreate request) {
@RequestBody QuestionCreate request) {

return BaseResponse.onSuccess(adminQuestionService.createQuestion(request));
}

@Operation(summary = "질문 삭제 API", description = "질문을 삭제합니다. 삭제할 질문의 ID를 입력하세요")
@ApiResponses(value = {
@ApiResponse(responseCode = "COMMON200", description = "성공,")
@ApiResponse(responseCode = "COMMON200", description = "성공,")
})
@DeleteMapping("/{questionId}")
public BaseResponse<QuestionId> deleteQuestion(
@PathVariable(value = "questionId") Long questionId) {
@PathVariable(value = "questionId") Long questionId) {

return BaseResponse.onSuccess(adminQuestionService.deleteQuestion(questionId));
}

@PostMapping(value = "/upload/csv", consumes = "text/csv")
public BaseResponse<Long> uploadQuestionByCsv(@RequestBody String text) {
return BaseResponse.onSuccess(adminQuestionService.uploadQuestionByCsv(text));
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package com.server.capple.domain.question.mapper;

import com.server.capple.domain.question.dto.internal.QuestionDto.QuestionInsertDto;
import com.server.capple.domain.question.dto.request.QuestionRequest.QuestionCreate;
import com.server.capple.domain.question.dto.response.QuestionResponse.QuestionInfo;
import com.server.capple.domain.question.dto.response.QuestionResponse.QuestionSummary;
import com.server.capple.domain.question.entity.Question;
import com.server.capple.domain.question.entity.QuestionStatus;
import org.springframework.stereotype.Component;

@Component
Expand Down Expand Up @@ -40,4 +42,11 @@ public QuestionInfo toQuestionInfo(Question question, boolean isAnswered/*, Inte
.isAnswered(isAnswered)
.build();
}

public Question toQuestionInsertDto(QuestionInsertDto questionInsertDto) {
return Question.builder()
.questionStatus(QuestionStatus.PENDING)
.content(questionInsertDto.getQuestionContent().trim())
.build();
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.server.capple.domain.member.entity.Member;
import com.server.capple.domain.question.dao.QuestionInfoInterface;
import com.server.capple.domain.question.entity.Question;
import com.server.capple.domain.question.entity.QuestionStatus;
import io.lettuce.core.dynamic.annotation.Param;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
Expand All @@ -12,6 +13,7 @@
import java.util.Optional;

public interface QuestionRepository extends JpaRepository<Question, Long> {
Optional<Question> findFirstByQuestionStatusOrderByIdAsc(QuestionStatus questionStatus);

@Query("SELECT q FROM Question q WHERE q.id = :questionId")
Optional<Question> findById(@Param("questionId") Long questionId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@ public interface AdminQuestionService {

Question setLiveQuestion();
Question closeLiveQuestion();
Long uploadQuestionByCsv(String text);

}
Original file line number Diff line number Diff line change
@@ -1,28 +1,36 @@
package com.server.capple.domain.question.service;

import com.opencsv.CSVReader;
import com.opencsv.bean.CsvToBeanBuilder;
import com.server.capple.domain.question.dto.internal.QuestionDto.QuestionInsertDto;
import com.server.capple.domain.question.dto.request.QuestionRequest.QuestionCreate;
import com.server.capple.domain.question.dto.response.QuestionResponse.QuestionId;
import com.server.capple.domain.question.entity.Question;
import com.server.capple.domain.question.entity.QuestionStatus;
import com.server.capple.domain.question.mapper.QuestionMapper;
import com.server.capple.domain.question.repository.AdminQuestionRepository;
import com.server.capple.domain.question.repository.QuestionRepository;
import com.server.capple.global.exception.RestApiException;
import com.server.capple.global.exception.errorCode.QuestionErrorCode;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.StringReader;
import java.util.List;

@Slf4j
@Service
@RequiredArgsConstructor
public class AdminQuestionServiceImpl implements AdminQuestionService {

private final AdminQuestionRepository adminQuestionRepository;
private final QuestionRepository questionRepository;
private final QuestionService questionService;
private final QuestionMapper questionMapper;

@Override
public QuestionId createQuestion(QuestionCreate request) {
Question question = adminQuestionRepository.save(questionMapper.toQuestion(request));
Question question = questionRepository.save(questionMapper.toQuestion(request));

return new QuestionId(question.getId());
}
Expand All @@ -40,8 +48,8 @@ public QuestionId deleteQuestion(Long questionId) {

@Transactional
public Question setLiveQuestion() {
Question newQuestion = adminQuestionRepository.findFirstByQuestionStatusOrderByIdAsc(QuestionStatus.PENDING)
.orElseThrow(() -> new RestApiException(QuestionErrorCode.QUESTION_PENDING_NOT_FOUND));
Question newQuestion = questionRepository.findFirstByQuestionStatusOrderByIdAsc(QuestionStatus.PENDING)
.orElseThrow(() -> new RestApiException(QuestionErrorCode.QUESTION_PENDING_NOT_FOUND));

newQuestion.setQuestionStatus(QuestionStatus.LIVE);

Expand All @@ -51,10 +59,24 @@ public Question setLiveQuestion() {

@Transactional
public Question closeLiveQuestion() {
Question question = adminQuestionRepository.findFirstByQuestionStatusOrderByIdAsc(QuestionStatus.LIVE)
.orElseThrow(() -> new RestApiException(QuestionErrorCode.QUESTION_LIVE_NOT_FOUND));
Question question = questionRepository.findFirstByQuestionStatusOrderByIdAsc(QuestionStatus.LIVE)
.orElseThrow(() -> new RestApiException(QuestionErrorCode.QUESTION_LIVE_NOT_FOUND));
question.setQuestionStatus(QuestionStatus.OLD);

return question;
}

@Override
public Long uploadQuestionByCsv(String text) {
List<QuestionInsertDto> questionInsertDtoList = new CsvToBeanBuilder(new CSVReader(new StringReader(text)))
.withType(QuestionInsertDto.class)
.build()
.parse();
List<Question> questions = questionInsertDtoList.stream()
.map(questionMapper::toQuestionInsertDto)
.toList();
Long savedQuestionCount = (long) questionRepository.saveAll(questions).size();
log.info("{} 개의 질문이 새롭게 추가되었습니다.", savedQuestionCount);
return savedQuestionCount;
}
}

0 comments on commit 2074dcf

Please sign in to comment.