Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ public class QProblem extends EntityPathBase<Problem> {

public final StringPath readingTipImageUrl = createString("readingTipImageUrl");

public final QRecommendedTime recommendedTime;

public final StringPath seniorTipImageUrl = createString("seniorTipImageUrl");

public final QTitle title;
Expand Down Expand Up @@ -89,6 +91,7 @@ public QProblem(Class<? extends Problem> type, PathMetadata metadata, PathInits
this.answer = inits.isInitialized("answer") ? new com.moplus.moplus_server.domain.problem.domain.QAnswer(forProperty("answer")) : null;
this.difficulty = inits.isInitialized("difficulty") ? new QDifficulty(forProperty("difficulty")) : null;
this.problemCustomId = inits.isInitialized("problemCustomId") ? new QProblemCustomId(forProperty("problemCustomId")) : null;
this.recommendedTime = inits.isInitialized("recommendedTime") ? new QRecommendedTime(forProperty("recommendedTime")) : null;
this.title = inits.isInitialized("title") ? new QTitle(forProperty("title")) : null;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.moplus.moplus_server.domain.problem.domain.problem;

import static com.querydsl.core.types.PathMetadataFactory.*;

import com.querydsl.core.types.dsl.*;

import com.querydsl.core.types.PathMetadata;
import javax.annotation.processing.Generated;
import com.querydsl.core.types.Path;


/**
* QRecommendedTime is a Querydsl query type for RecommendedTime
*/
@Generated("com.querydsl.codegen.DefaultEmbeddableSerializer")
public class QRecommendedTime extends BeanPath<RecommendedTime> {

private static final long serialVersionUID = -1102611877L;

public static final QRecommendedTime recommendedTime = new QRecommendedTime("recommendedTime");

public final NumberPath<Integer> minute = createNumber("minute", Integer.class);

public final NumberPath<Integer> second = createNumber("second", Integer.class);

public QRecommendedTime(String variable) {
super(RecommendedTime.class, forVariable(variable));
}

public QRecommendedTime(Path<? extends RecommendedTime> path) {
super(path.getType(), path.getMetadata());
}

public QRecommendedTime(PathMetadata metadata) {
super(RecommendedTime.class, metadata);
}

}

Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

@Generated(
value = "org.mapstruct.ap.MappingProcessor",
date = "2025-02-18T19:54:34+0900",
date = "2025-02-18T21:41:47+0900",
comments = "version: 1.6.3, compiler: javac, environment: Java 17.0.10 (JetBrains s.r.o.)"
)
@Component
Expand Down Expand Up @@ -48,6 +48,8 @@ public Problem from(ProblemUpdateRequest request, ProblemCustomId problemCustomI
Problem.ProblemBuilder problem = Problem.builder();

if ( request != null ) {
problem.recommendedMinute( request.recommendedMinute() );
problem.recommendedSecond( request.recommendedSecond() );
problem.answerType( request.answerType() );
Set<Long> set = request.conceptTagIds();
if ( set != null ) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@ public class ProblemSearchController {
)
public ResponseEntity<List<ProblemSearchGetResponse>> search(
@RequestParam(value = "problemCustomId", required = false) String problemCustomId,
@RequestParam(value = "comment", required = false) String comment,
@RequestParam(value = "memo", required = false) String memo,
@RequestParam(value = "conceptTagIds", required = false) List<Long> conceptTagIds
) {
List<ProblemSearchGetResponse> problems = problemSearchRepository.search(problemCustomId, comment,
List<ProblemSearchGetResponse> problems = problemSearchRepository.search(problemCustomId, memo,
conceptTagIds);
return ResponseEntity.ok(problems);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,13 +80,16 @@ public class Problem extends BaseEntity {
@OrderColumn(name = "sequence")
private List<ChildProblem> childProblems = new ArrayList<>();

@Embedded
private RecommendedTime recommendedTime;

@Builder
public Problem(List<ChildProblem> childProblems, boolean isConfirmed, AnswerType answerType,
Set<Long> conceptTagIds, Integer difficulty, String mainHandwritingExplanationImageUrl,
List<String> prescriptionImageUrls, String seniorTipImageUrl, String readingTipImageUrl,
String mainAnalysisImageUrl, String mainProblemImageUrl, String memo, String answer, String title,
ProblemType problemType, int number, PracticeTestTag practiceTestTag,
ProblemCustomId problemCustomId) {
ProblemCustomId problemCustomId, Integer recommendedMinute, Integer recommendedSecond) {
this.childProblems = childProblems;
this.isConfirmed = isConfirmed;
this.answerType = answerType;
Expand All @@ -105,6 +108,7 @@ public Problem(List<ChildProblem> childProblems, boolean isConfirmed, AnswerType
this.number = number;
this.practiceTestId = practiceTestTag != null ? practiceTestTag.getId() : null;
this.problemCustomId = problemCustomId;
this.recommendedTime = new RecommendedTime(recommendedMinute, recommendedSecond);
}

public String getAnswer() {
Expand All @@ -123,11 +127,15 @@ public void update(Problem inputProblem) {
this.memo = inputProblem.getMemo();
this.mainProblemImageUrl = inputProblem.getMainProblemImageUrl();
this.mainAnalysisImageUrl = inputProblem.getMainAnalysisImageUrl();
this.mainHandwritingExplanationImageUrl = inputProblem.getMainHandwritingExplanationImageUrl(); // 추가
this.mainHandwritingExplanationImageUrl = inputProblem.getMainHandwritingExplanationImageUrl();
this.readingTipImageUrl = inputProblem.getReadingTipImageUrl();
this.seniorTipImageUrl = inputProblem.getSeniorTipImageUrl();
this.prescriptionImageUrls = inputProblem.getPrescriptionImageUrls();
this.answerType = inputProblem.getAnswerType();
this.recommendedTime = new RecommendedTime(
inputProblem.getRecommendedTime() != null ? inputProblem.getRecommendedTime().getMinute() : null,
inputProblem.getRecommendedTime() != null ? inputProblem.getRecommendedTime().getSecond() : null
);
}

public void updateChildProblem(List<ChildProblem> inputChildProblems) {
Expand Down Expand Up @@ -156,7 +164,8 @@ public boolean isValid() {
&& prescriptionImageUrls != null && !prescriptionImageUrls.isEmpty()
&& prescriptionImageUrls.stream().allMatch(url -> url != null && !url.isEmpty())
&& answerType != null
&& conceptTagIds != null && !conceptTagIds.isEmpty();
&& conceptTagIds != null && !conceptTagIds.isEmpty()
&& recommendedTime != null;
}

public String getTitle() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.moplus.moplus_server.domain.problem.domain.problem;

import com.moplus.moplus_server.global.error.exception.ErrorCode;
import com.moplus.moplus_server.global.error.exception.InvalidValueException;
import jakarta.persistence.Column;
import jakarta.persistence.Embeddable;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@Embeddable
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class RecommendedTime {
@Column(name = "recommended_minute")
private Integer minute;
@Column(name = "recommended_second")
private Integer second;

public RecommendedTime(Integer minute, Integer second) {
validateTime(minute, second);
this.minute = minute;
this.second = second;
}

private void validateTime(Integer minute, Integer second) {
if (minute != null && (minute < 0 || minute > 60)) {
throw new InvalidValueException(ErrorCode.INVALID_INPUT_VALUE);
}
if (second != null && (second < 0 || second > 60)) {
throw new InvalidValueException(ErrorCode.INVALID_INPUT_VALUE);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ public record ProblemUpdateRequest(
String seniorTipImageUrl,
List<String> prescriptionImageUrls,
AnswerType answerType,
List<ChildProblemUpdateRequest> updateChildProblems
List<ChildProblemUpdateRequest> updateChildProblems,
Integer recommendedMinute,
Integer recommendedSecond
) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@ public record ProblemGetResponse(
String readingTipImageUrl,
String seniorTipImageUrl,
List<String> prescriptionImageUrls,
List<ChildProblemGetResponse> childProblems
List<ChildProblemGetResponse> childProblems,
Integer recommendedMinute,
Integer recommendedSecond
) {

public static ProblemGetResponse of(Problem problem) {
Expand All @@ -55,6 +57,8 @@ public static ProblemGetResponse of(Problem problem) {
.childProblems(problem.getChildProblems().stream()
.map(ChildProblemGetResponse::of)
.toList())
.recommendedMinute(problem.getRecommendedTime().getMinute())
.recommendedSecond(problem.getRecommendedTime().getSecond())
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,13 @@ public class ProblemSearchRepositoryCustom {

private final JPAQueryFactory queryFactory;

public List<ProblemSearchGetResponse> search(String problemId, String comment, List<Long> conceptTagIds) {
public List<ProblemSearchGetResponse> search(String problemId, String memo, List<Long> conceptTagIds) {
return queryFactory
.select(problem.problemCustomId.id, problem.memo, problem.mainProblemImageUrl)
.from(problem)
.where(
containsProblemId(problemId),
containsName(comment),
containsName(memo),
inConceptTagIds(conceptTagIds)
)
.leftJoin(conceptTag).on(conceptTag.id.in(problem.conceptTagIds)).fetchJoin()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ public interface ProblemMapper {
@Mappings({
@Mapping(target = "problemCustomId", source = "problemCustomId"),
@Mapping(target = "practiceTestTag", source = "practiceTestTag"),
@Mapping(target = "recommendedMinute", source = "request.recommendedMinute"),
@Mapping(target = "recommendedSecond", source = "request.recommendedSecond")
})
Problem from(ProblemUpdateRequest request, ProblemCustomId problemCustomId, PracticeTestTag practiceTestTag);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.transaction.annotation.Transactional;

@Transactional
@ExtendWith(MockitoExtension.class)
class ProblemCustomIdServiceTest {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,12 +71,14 @@ void setUp() {
"업데이트된 메모",
"updatedMainProblem.png",
"updatedMainAnalysis.png",
"updatedMainHandwriting.png", // 추가
"updatedMainHandwriting.png",
"updatedReadingTip.png",
"updatedSeniorTip.png",
List.of("prescription1.png", "prescription2.png"), // List<String>으로 변경
List.of("prescription1.png", "prescription2.png"),
AnswerType.SHORT_STRING_ANSWER,
List.of(updateChildProblem1, updateChildProblem2)
List.of(updateChildProblem1, updateChildProblem2),
30,
45
);
}

Expand Down Expand Up @@ -133,6 +135,10 @@ class 문제_업데이트_정상_동작 {
assertThat(newChild.getAnswerType()).isEqualTo(AnswerType.SHORT_STRING_ANSWER);
assertThat(newChild.getAnswer()).isEqualTo("23");
assertThat(newChild.getConceptTagIds()).containsExactlyInAnyOrderElementsOf(Set.of(3L, 4L));

// 추가된 검증
assertThat(response.recommendedMinute()).isEqualTo(30);
assertThat(response.recommendedSecond()).isEqualTo(45);
}
}

Expand Down Expand Up @@ -163,12 +169,14 @@ class 문제_업데이트_예외_처리 {
"잘못된 메모",
"updatedMainProblem.png",
"updatedMainAnalysis.png",
"updatedMainHandwriting.png", // 추가
"updatedMainHandwriting.png",
"updatedReadingTip.png",
"updatedSeniorTip.png",
List.of("prescription1.png"), // List<String>으로 변경
List.of("prescription1.png"),
AnswerType.SHORT_STRING_ANSWER,
List.of()
List.of(),
30,
45
);

// when & then
Expand Down
2 changes: 2 additions & 0 deletions src/test/resources/concept-tag.sql
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
DELETE FROM concept_tag;

INSERT INTO concept_tag (concept_tag_id, name)
VALUES (1, '미분 개념'),
(2, '적분 개념'),
Expand Down
51 changes: 41 additions & 10 deletions src/test/resources/insert-problem.sql
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
DELETE FROM child_problem_concept;
DELETE FROM problem_concept;
DELETE FROM child_problem;
DELETE FROM problem;

-- 데이터 삽입
INSERT INTO problem (problem_id,
problem_custom_id,
practice_test_id,
Expand All @@ -13,35 +19,60 @@ INSERT INTO problem (problem_id,
senior_tip_image_url,
prescription_image_urls,
answer_type,
is_confirmed)
is_confirmed,
recommended_minute,
recommended_second)
VALUES (1, '1224052001', 1, 1, 'GICHUL_PROBLEM', '제목1', '1', 5, '기존 문제 설명 1',
'mainProblem.png1', 'mainAnalysis.png1', 'readingTip.png1', 'seniorTip.png1',
'prescription.png1', 'MULTIPLE_CHOICE', false),
'prescription.png1', 'MULTIPLE_CHOICE', false, 30, 45),
(2, '1224052002', 1, 1, 'GICHUL_PROBLEM', '제목2', '1', 5, '기존 문제 설명 2',
'mainProblem.png2', 'mainAnalysis.png2', 'readingTip.png2', 'seniorTip.png2',
'prescription.png2', 'MULTIPLE_CHOICE', false);
'prescription.png2', 'MULTIPLE_CHOICE', false, 25, 30);

-- 자식 문제 테이블 생성
CREATE TABLE IF NOT EXISTS child_problem (
child_problem_id BIGINT PRIMARY KEY,
problem_id BIGINT,
image_url VARCHAR(255),
answer_type VARCHAR(50),
answer VARCHAR(255),
sequence INT
);

-- 자식 문제 데이터 삽입
INSERT INTO child_problem (child_problem_id,
problem_id, -- Long 타입으로 변경 (부모 Problem의 id 참조)
problem_id,
image_url,
answer_type,
answer,
sequence)
VALUES (1, 1, 'child1.png', 'MULTIPLE_CHOICE', '1', 0),
(2, 1, 'child2.png', 'SHORT_STRING_ANSWER', '정답2', 1);

-- 문제-컨셉 태그 연결 (기존 문제의 ConceptTag)
INSERT INTO problem_concept (problem_id, -- Long 타입으로 변경 (Problem의 id 참조)
concept_tag_id)
-- 문제-컨셉 태그 연결 테이블 생성
CREATE TABLE IF NOT EXISTS problem_concept (
problem_id BIGINT,
concept_tag_id BIGINT,
PRIMARY KEY (problem_id, concept_tag_id)
);

-- 문제-컨셉 태그 데이터 삽입
INSERT INTO problem_concept (problem_id, concept_tag_id)
VALUES (1, 1),
(1, 2),
(1, 3),
(2, 1),
(2, 3);

-- 자식 문제-컨셉 태그 연결
INSERT INTO child_problem_concept (child_problem_id,
concept_tag_id)
-- 자식 문제-컨셉 태그 연결 테이블 생성
CREATE TABLE IF NOT EXISTS child_problem_concept (
child_problem_id BIGINT,
concept_tag_id BIGINT,
PRIMARY KEY (child_problem_id, concept_tag_id)
);

-- 자식 문제-컨셉 태그 데이터 삽입
INSERT INTO child_problem_concept (child_problem_id, concept_tag_id)
VALUES (1, 3),
(1, 4),
(2, 5),
Expand Down
Loading