Skip to content

Commit 2b9349e

Browse files
committed
✨ feat : 퀴즈 생성 기능 구현
1 parent 2d3c46d commit 2b9349e

File tree

21 files changed

+367
-3
lines changed

21 files changed

+367
-3
lines changed

backend/.gitignore

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,7 @@ out/
4040
.env
4141

4242
### .idea ###
43-
.idea
43+
.idea
44+
45+
### images/thumbnail ###
46+
images/thumbnail/**
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package io.f1.backend.domain.question.app;
2+
3+
import io.f1.backend.domain.question.dao.QuestionRepository;
4+
import io.f1.backend.domain.question.dao.TextQuestionRepository;
5+
import io.f1.backend.domain.question.dto.QuestionRequest;
6+
import io.f1.backend.domain.question.entity.Question;
7+
import io.f1.backend.domain.question.entity.TextQuestion;
8+
import io.f1.backend.domain.question.mapper.QuestionMapper;
9+
import io.f1.backend.domain.question.mapper.TextQuestionMapper;
10+
import io.f1.backend.domain.quiz.entity.Quiz;
11+
import lombok.RequiredArgsConstructor;
12+
import org.springframework.stereotype.Service;
13+
import org.springframework.transaction.annotation.Transactional;
14+
15+
@Service
16+
@RequiredArgsConstructor
17+
public class QuestionService {
18+
19+
private final QuestionRepository questionRepository;
20+
private final TextQuestionRepository textQuestionRepository;
21+
22+
@Transactional
23+
public void saveQuestion(Quiz quiz, QuestionRequest request) {
24+
25+
Question question = QuestionMapper.questionRequestToQuestion(quiz, request);
26+
quiz.addQuestion(question);
27+
questionRepository.save(question);
28+
29+
TextQuestion textQuestion = TextQuestionMapper.questionRequestToTextQuestion(question, request.getContent());
30+
textQuestionRepository.save(textQuestion);
31+
question.addTextQuestion(textQuestion);
32+
33+
}
34+
35+
36+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package io.f1.backend.domain.question.dao;
2+
3+
import io.f1.backend.domain.question.entity.Question;
4+
import org.springframework.data.jpa.repository.JpaRepository;
5+
6+
public interface QuestionRepository extends JpaRepository<Question, Long> {
7+
8+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package io.f1.backend.domain.question.dao;
2+
3+
import io.f1.backend.domain.question.entity.TextQuestion;
4+
import org.springframework.data.jpa.repository.JpaRepository;
5+
6+
public interface TextQuestionRepository extends JpaRepository<TextQuestion, Long> {
7+
8+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package io.f1.backend.domain.question.dto;
2+
3+
import jakarta.validation.constraints.NotBlank;
4+
import lombok.AccessLevel;
5+
import lombok.Getter;
6+
import lombok.NoArgsConstructor;
7+
8+
@Getter
9+
@NoArgsConstructor(access= AccessLevel.PROTECTED)
10+
public class QuestionRequest {
11+
12+
@NotBlank(message="문제를 입력해주세요.")
13+
private String content;
14+
15+
@NotBlank(message="정답을 입력해주세요.")
16+
private String answer;
17+
18+
}

backend/src/main/java/io/f1/backend/domain/question/entity/Question.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,11 @@
1313
import jakarta.persistence.JoinColumn;
1414
import jakarta.persistence.ManyToOne;
1515
import jakarta.persistence.OneToOne;
16+
import lombok.AccessLevel;
17+
import lombok.NoArgsConstructor;
1618

1719
@Entity
20+
@NoArgsConstructor(access= AccessLevel.PROTECTED)
1821
public class Question extends BaseEntity {
1922

2023
@Id
@@ -30,4 +33,13 @@ public class Question extends BaseEntity {
3033

3134
@OneToOne(mappedBy = "question", cascade = CascadeType.REMOVE)
3235
private TextQuestion textQuestion;
36+
public Question(Quiz quiz, String answer) {
37+
this.quiz = quiz;
38+
this.answer = answer;
39+
}
40+
41+
public void addTextQuestion(TextQuestion textQuestion) {
42+
this.textQuestion = textQuestion;
43+
}
44+
3345
}

backend/src/main/java/io/f1/backend/domain/question/entity/TextQuestion.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,11 @@
77
import jakarta.persistence.Id;
88
import jakarta.persistence.JoinColumn;
99
import jakarta.persistence.OneToOne;
10+
import lombok.AccessLevel;
11+
import lombok.NoArgsConstructor;
1012

1113
@Entity
14+
@NoArgsConstructor(access= AccessLevel.PROTECTED)
1215
public class TextQuestion {
1316

1417
@Id
@@ -21,4 +24,9 @@ public class TextQuestion {
2124

2225
@Column(nullable = false)
2326
private String content;
27+
28+
public TextQuestion(Question question, String content) {
29+
this.question = question;
30+
this.content = content;
31+
}
2432
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package io.f1.backend.domain.question.mapper;
2+
3+
import io.f1.backend.domain.question.dto.QuestionRequest;
4+
import io.f1.backend.domain.question.entity.Question;
5+
import io.f1.backend.domain.quiz.entity.Quiz;
6+
7+
public class QuestionMapper {
8+
9+
public static Question questionRequestToQuestion(Quiz quiz, QuestionRequest questionRequest) {
10+
return new Question(quiz, questionRequest.getAnswer());
11+
}
12+
13+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package io.f1.backend.domain.question.mapper;
2+
3+
import io.f1.backend.domain.question.entity.Question;
4+
import io.f1.backend.domain.question.entity.TextQuestion;
5+
6+
public class TextQuestionMapper {
7+
8+
public static TextQuestion questionRequestToTextQuestion(Question question, String content) {
9+
return new TextQuestion(question, content);
10+
}
11+
12+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package io.f1.backend.domain.quiz.api;
2+
3+
import io.f1.backend.domain.quiz.app.QuizService;
4+
import io.f1.backend.domain.quiz.dto.QuizCreateRequest;
5+
import io.f1.backend.domain.quiz.dto.QuizCreateResponse;
6+
import jakarta.validation.Valid;
7+
import java.io.IOException;
8+
import lombok.RequiredArgsConstructor;
9+
import org.springframework.http.HttpStatus;
10+
import org.springframework.http.MediaType;
11+
import org.springframework.http.ResponseEntity;
12+
import org.springframework.web.bind.annotation.PostMapping;
13+
import org.springframework.web.bind.annotation.RequestMapping;
14+
import org.springframework.web.bind.annotation.RequestPart;
15+
import org.springframework.web.bind.annotation.RestController;
16+
import org.springframework.web.multipart.MultipartFile;
17+
18+
@RestController
19+
@RequestMapping("/quizzes")
20+
@RequiredArgsConstructor
21+
public class QuizController {
22+
23+
private final QuizService quizService;
24+
25+
@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
26+
public ResponseEntity<QuizCreateResponse> saveQuiz(@RequestPart(required = false) MultipartFile file, @Valid @RequestPart QuizCreateRequest request) throws IOException {
27+
QuizCreateResponse response = quizService.saveQuiz(file, request);
28+
29+
return ResponseEntity.status(HttpStatus.CREATED).body(response);
30+
}
31+
32+
}

0 commit comments

Comments
 (0)