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 @@ -44,10 +44,10 @@ public ResponseEntity<ApiResponse<QuestionResDTO.QuestionDetailResponse>> getQue
public ResponseEntity<ApiResponse<QuestionResDTO.CreateRes>> createQuestion(
@PathVariable Long sessionId,
@RequestBody QuestionReqDTO.CreateReq request,
@AuthenticationPrincipal Integer userId
@AuthenticationPrincipal Long userId
) {
return ResponseUtil.success(QuestionSuccessCode.QUESTION_CREATED,
questionService.createQuestion(sessionId, request, Long.valueOf(userId)));
questionService.createQuestion(sessionId, request, userId));
}

// 댓글/대댓글 등록
Expand All @@ -73,6 +73,29 @@ public ResponseEntity<ApiResponse<QuestionResDTO.LikeRes>> toggleLike(
questionService.toggleLike(questionId, userId));
}

// 질문 수정
// PATCH /api/questions/{questionId}/modify
@PatchMapping("/api/questions/{questionId}/modify")
public ResponseEntity<ApiResponse<QuestionResDTO.UpdateDeleteRes>> updateQuestion(
@PathVariable Long questionId,
@RequestBody QuestionReqDTO.UpdateReq request,
@AuthenticationPrincipal Long userId
) {
return ResponseUtil.success(QuestionSuccessCode.QUESTION_UPDATED,
questionService.updateQuestion(questionId, request, userId));
}

// 질문 삭제
// DELETE /api/questions/{questionId}
@DeleteMapping("/api/questions/{questionId}")
public ResponseEntity<ApiResponse<QuestionResDTO.UpdateDeleteRes>> deleteQuestion(
@PathVariable Long questionId,
@AuthenticationPrincipal Long userId
) {
return ResponseUtil.success(QuestionSuccessCode.QUESTION_DELETED,
questionService.deleteQuestion(questionId, userId));
}

// 이해도 체크 생성
// POST /api/sessions/{sessionId}/understanding-checks
@PostMapping("/api/sessions/{sessionId}/understanding-checks")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,13 @@ public static class CreateReq {
private String content;
}

// 질문 수정 요청
@Getter
@NoArgsConstructor
public static class UpdateReq {
private String content;
}

// 댓글/대댓글 등록 요청
// parentCommentId가 null이면 일반 댓글, 값이 있으면 대댓글
@Getter
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,16 @@ public record LikeRes(
) {
}

// 질문 수정/삭제 응답 (형태가 동일해서 하나로 공유)
// deletedAt에 값이 있으면 삭제된 상태
public record UpdateDeleteRes(
Long id,
String content,
LocalDateTime updatedAt,
LocalDateTime deletedAt
) {
}

// 질문 상세 응답
public record QuestionDetailResponse(
Long questionId,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,4 +67,16 @@ public void decreaseLikeCount() {
}
this.updatedAt = LocalDateTime.now();
}

// 질문 내용 수정
public void updateContent(String content) {
this.content = content;
this.updatedAt = LocalDateTime.now();
}

// 질문 소프트 삭제 (DB에서 실제로 지우지 않고 deleted_at에 시각 기록)
public void softDelete() {
this.deletedAt = LocalDateTime.now();
this.updatedAt = LocalDateTime.now();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@ public enum QuestionSuccessCode implements BaseCode {

QUESTION_ROOM_OK(HttpStatus.OK, "QUESTION200_1", "질문 방 조회에 성공했습니다."),
QUESTION_DETAIL_OK(HttpStatus.OK, "QUESTION200_2", "질문 상세 조회에 성공했습니다."),
LIKE_TOGGLED(HttpStatus.OK, "QUESTION200_3", "좋아요가 처리되었습니다."), // ← 추가
LIKE_TOGGLED(HttpStatus.OK, "QUESTION200_3", "좋아요가 처리되었습니다."),
UNDERSTANDING_RESPONSE_OK(HttpStatus.OK, "QUESTION200_4", "이해도 응답이 반영되었습니다."),
QUESTION_UPDATED(HttpStatus.OK, "QUESTION200_5", "질문이 수정되었습니다."),
QUESTION_DELETED(HttpStatus.OK, "QUESTION200_6", "질문이 삭제되었습니다."),
QUESTION_CREATED(HttpStatus.CREATED, "QUESTION201_1", "질문이 등록되었습니다."),
COMMENT_CREATED(HttpStatus.CREATED, "QUESTION201_2", "댓글이 등록되었습니다."),
UNDERSTANDING_CHECK_CREATED(HttpStatus.CREATED, "QUESTION201_3", "이해도 체크가 생성되었습니다.");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,40 @@ public QuestionResDTO.LikeRes toggleLike(Long questionId, Long userId) {
});
}

// 질문 수정
@Transactional
public QuestionResDTO.UpdateDeleteRes updateQuestion(
Long questionId,
QuestionReqDTO.UpdateReq request,
Long userId
) {
User loginUser = findLoginUser(userId);
Question question = findQuestion(questionId);
validateQuestionOwner(question, loginUser);

question.updateContent(request.getContent());

return new QuestionResDTO.UpdateDeleteRes(
question.getId(), question.getContent(),
question.getUpdatedAt(), question.getDeletedAt()
);
}

// 질문 삭제
@Transactional
public QuestionResDTO.UpdateDeleteRes deleteQuestion(Long questionId, Long userId) {
User loginUser = findLoginUser(userId);
Question question = findQuestion(questionId);
validateQuestionOwner(question, loginUser);

question.softDelete();

return new QuestionResDTO.UpdateDeleteRes(
question.getId(), question.getContent(),
question.getUpdatedAt(), question.getDeletedAt()
);
}

// 이해도 체크 생성
@Transactional
public QuestionResDTO.UnderstandingCheckCreateResponse createUnderstandingCheck(
Expand Down Expand Up @@ -320,6 +354,12 @@ private void validateCheckBelongsToSession(UnderstandingCheck check, StudySessio
}
}

private void validateQuestionOwner(Question question, User loginUser) {
if (!question.getUser().getId().equals(loginUser.getId())) {
throw new QuestionException(HttpStatus.FORBIDDEN, "본인의 질문만 수정/삭제할 수 있습니다.");
}
}

private UnderstandResChoice applyUnderstandingResponse(
UnderstandingCheck check, User loginUser, UnderstandResChoice requestedChoice
) {
Expand Down
Loading