Skip to content

Commit 9ac32d0

Browse files
committed
[feat] #53 resume update question order
1 parent 2663b30 commit 9ac32d0

File tree

7 files changed

+156
-5
lines changed

7 files changed

+156
-5
lines changed

src/main/java/com/example/dgu/returnwork/domain/resume/controller/ResumeApi.java

Lines changed: 100 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import com.example.dgu.returnwork.domain.resume.dto.request.CreateResumeQuestionRequestDto;
44
import com.example.dgu.returnwork.domain.resume.dto.request.CreateResumeRequestDto;
5+
import com.example.dgu.returnwork.domain.resume.dto.request.UpdateQuestionOrderRequestDto;
56
import com.example.dgu.returnwork.domain.resume.dto.response.CreateResumeResponseDto;
67
import com.example.dgu.returnwork.domain.resume.dto.response.GetResumeQuestionListResponseDto;
78
import com.example.dgu.returnwork.domain.resume.dto.response.SetResumeResponseDto;
@@ -455,6 +456,103 @@ void deleteDraftResume(
455456
@Parameter(hidden = true) @CurrentUser User user,
456457
@Parameter(description = "삭제할 자소서 ID", example = "1") @PathVariable Long resumeId
457458
);
458-
459-
459+
460+
@Operation(
461+
summary = "자소서 질문 순서 변경 API",
462+
description = """
463+
특정 자소서 질문의 순서(questionOrder)를 변경하는 API입니다.
464+
465+
## 동작 방식:
466+
- 지정한 질문의 순서 번호만 업데이트
467+
- 다른 질문들의 순서는 자동으로 변경되지 않음
468+
- 중복된 순서 번호 허용
469+
470+
## 제한사항:
471+
- DRAFT 상태의 자소서에서만 수정 가능
472+
- 본인이 작성한 자소서의 질문만 수정 가능
473+
"""
474+
)
475+
@SecurityRequirement(name = "JWT")
476+
@ApiResponses({
477+
@ApiResponse(responseCode = "200", description = "질문 순서 변경 성공",
478+
content = @Content(mediaType = "application/json",
479+
schema = @Schema(implementation = com.example.dgu.returnwork.global.response.ApiResponse.class),
480+
examples = @ExampleObject(
481+
name = "성공 응답",
482+
value = """
483+
{
484+
"errorCode": null,
485+
"message": "OK",
486+
"result": null
487+
}
488+
"""
489+
)
490+
)
491+
),
492+
@ApiResponse(responseCode = "400", description = "잘못된 요청",
493+
content = @Content(mediaType = "application/json",
494+
schema = @Schema(implementation = CustomErrorResponse.class),
495+
examples = {
496+
@ExampleObject(
497+
name = "검증 실패",
498+
summary = "입력값 검증 실패",
499+
value = """
500+
{
501+
"status" : 400,
502+
"errorCode" : "COMMON_002",
503+
"message" : "입력값 검증에 실패했습니다"
504+
}
505+
"""
506+
),
507+
@ExampleObject(
508+
name = "완료된 자소서",
509+
summary = "이미 작성 완료된 자소서",
510+
value = """
511+
{
512+
"status" : 400,
513+
"errorCode" : "RESUME_002",
514+
"message" : "이미 작성 완료된 자소서입니다."
515+
}
516+
"""
517+
)
518+
}
519+
)
520+
),
521+
@ApiResponse(responseCode = "401", description = "유효하지 않은 토큰인 경우",
522+
content = @Content(mediaType = "application/json",
523+
schema = @Schema(implementation = CustomErrorResponse.class),
524+
examples = @ExampleObject(
525+
name = "유효하지 않은 토큰",
526+
value = """
527+
{
528+
"status" : 401,
529+
"errorCode" : "AUTH_001",
530+
"message" : "유효하지 않는 토큰입니다."
531+
}
532+
"""
533+
)
534+
)
535+
),
536+
@ApiResponse(responseCode = "404", description = "리소스를 찾을 수 없는 경우",
537+
content = @Content(mediaType = "application/json",
538+
schema = @Schema(implementation = CustomErrorResponse.class),
539+
examples = @ExampleObject(
540+
name = "질문 없음",
541+
value = """
542+
{
543+
"status" : 404,
544+
"errorCode" : "RESUME_003",
545+
"message" : "해당 질문을 찾을 수 없습니다."
546+
}
547+
"""
548+
)
549+
)
550+
)
551+
})
552+
void updateQuestionOrder(
553+
@Parameter(hidden = true) @CurrentUser User user,
554+
@Parameter(description = "자소서 ID", example = "1") @PathVariable Long resumeId,
555+
@Parameter(description = "질문 ID", example = "3") @PathVariable Long resumeQuestionId,
556+
@Valid @RequestBody UpdateQuestionOrderRequestDto request
557+
);
460558
}

src/main/java/com/example/dgu/returnwork/domain/resume/controller/ResumeController.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,13 @@
22

33
import com.example.dgu.returnwork.domain.resume.dto.request.CreateResumeQuestionRequestDto;
44
import com.example.dgu.returnwork.domain.resume.dto.request.CreateResumeRequestDto;
5+
import com.example.dgu.returnwork.domain.resume.dto.request.UpdateQuestionOrderRequestDto;
56
import com.example.dgu.returnwork.domain.resume.dto.response.CreateResumeResponseDto;
6-
import com.example.dgu.returnwork.domain.resume.dto.response.GetResumeDetailResponseDto;
77
import com.example.dgu.returnwork.domain.resume.dto.response.GetResumeQuestionListResponseDto;
88
import com.example.dgu.returnwork.domain.resume.dto.response.SetResumeResponseDto;
99
import com.example.dgu.returnwork.domain.resume.service.ResumeCommandService;
1010
import com.example.dgu.returnwork.domain.resume.service.ResumeQueryService;
1111
import com.example.dgu.returnwork.domain.user.User;
12-
import com.example.dgu.returnwork.domain.user.service.UserQueryService;
1312
import com.example.dgu.returnwork.global.annotation.CurrentUser;
1413
import lombok.RequiredArgsConstructor;
1514
import org.springframework.web.bind.annotation.*;
@@ -50,4 +49,12 @@ public void createResumeQuestion(User user, Long resumeId, CreateResumeQuestionR
5049
public void deleteDraftResume(@CurrentUser User user, @PathVariable Long resumeId) {
5150
resumeCommandService.deleteDraftResume(user, resumeId);
5251
}
52+
53+
@PatchMapping("/{resumeId}/{resumeQuestionId}")
54+
public void updateQuestionOrder(@CurrentUser User user,
55+
@PathVariable Long resumeId,
56+
@PathVariable Long resumeQuestionId,
57+
@RequestBody UpdateQuestionOrderRequestDto request){
58+
resumeCommandService.updateQuestionOrder(user, resumeId, resumeQuestionId, request);
59+
}
5360
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package com.example.dgu.returnwork.domain.resume.dto.request;
2+
3+
import io.swagger.v3.oas.annotations.media.Schema;
4+
import jakarta.validation.constraints.NotNull;
5+
6+
public record UpdateQuestionOrderRequestDto(
7+
@NotNull
8+
@Schema(example = "3")
9+
Integer questionOrder
10+
) {
11+
}

src/main/java/com/example/dgu/returnwork/domain/resume/entity/ResumeQuestion.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,4 +56,8 @@ public static ResumeQuestion create(Integer questionOrder,
5656
.build();
5757
}
5858

59+
public void updateQuestionOrder(Integer questionOrder){
60+
this.questionOrder = questionOrder;
61+
}
62+
5963
}

src/main/java/com/example/dgu/returnwork/domain/resume/exception/ResumeErrorCode.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@
1010
public enum ResumeErrorCode implements ErrorCode{
1111

1212
NOT_FOUND_RESUME(HttpStatus.NOT_FOUND, "RESUME_001", "자소서를 찾을 수 없습니다."),
13-
ALREADY_COMPLETED_RESUME(HttpStatus.BAD_REQUEST, "RESUME_002", "이미 작성 완료된 자소서입니다.")
13+
ALREADY_COMPLETED_RESUME(HttpStatus.BAD_REQUEST, "RESUME_002", "이미 작성 완료된 자소서입니다."),
14+
NOT_FOUND_RESUME_QUESTION(HttpStatus.NOT_FOUND, "RESUME_003", "자소서 세부문항을 찾을 수 없습니다.")
1415
;
1516

1617
private final HttpStatus status;

src/main/java/com/example/dgu/returnwork/domain/resume/repository/ResumeQuestionRepository.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,20 @@
22

33
import com.example.dgu.returnwork.domain.resume.entity.ResumeQuestion;
44
import org.springframework.data.jpa.repository.JpaRepository;
5+
import org.springframework.data.jpa.repository.Query;
6+
import org.springframework.data.repository.query.Param;
7+
8+
import java.util.Optional;
9+
import java.util.UUID;
510

611
public interface ResumeQuestionRepository extends JpaRepository<ResumeQuestion, Long> {
12+
13+
Optional<ResumeQuestion> findByResumeIdAndId(Long resumeId, Long resumeQuestionId);
14+
15+
@Query("SELECT rq FROM ResumeQuestion rq JOIN rq.resume r WHERE rq.id = :questionId AND r.id = :resumeId AND r.user.id = :userId")
16+
Optional<ResumeQuestion> findByIdAndResumeIdAndResumeUserId(
17+
@Param("questionId") Long questionId,
18+
@Param("resumeId") Long resumeId,
19+
@Param("userId") UUID userId
20+
);
721
}

src/main/java/com/example/dgu/returnwork/domain/resume/service/ResumeCommandService.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import com.example.dgu.returnwork.domain.job.service.JobQueryService;
55
import com.example.dgu.returnwork.domain.resume.dto.request.CreateResumeQuestionRequestDto;
66
import com.example.dgu.returnwork.domain.resume.dto.request.CreateResumeRequestDto;
7+
import com.example.dgu.returnwork.domain.resume.dto.request.UpdateQuestionOrderRequestDto;
78
import com.example.dgu.returnwork.domain.resume.dto.response.CreateResumeResponseDto;
89
import com.example.dgu.returnwork.domain.resume.entity.Resume;
910
import com.example.dgu.returnwork.domain.resume.entity.ResumeQuestion;
@@ -69,6 +70,21 @@ public void deleteDraftResume(User user, Long resumeId){
6970
resumeRepository.delete(resume);
7071
}
7172

73+
@Transactional
74+
public void updateQuestionOrder(User user,
75+
Long resumeId,
76+
Long resumeQuestionId,
77+
UpdateQuestionOrderRequestDto request){
78+
79+
ResumeQuestion resumeQuestion = resumeQuestionRepository
80+
.findByIdAndResumeIdAndResumeUserId(resumeQuestionId,resumeId, user.getId())
81+
.orElseThrow(() -> BaseException.type(ResumeErrorCode.NOT_FOUND_RESUME_QUESTION));
82+
83+
resumeValidator.validateDraftStatus(resumeQuestion.getResume().getResumeStatus());
84+
85+
resumeQuestion.updateQuestionOrder(request.questionOrder());
86+
}
87+
7288
private void addResumeQuestions(int count, Resume resume){
7389

7490
for (int i = 1; i <=count; i++) {

0 commit comments

Comments
 (0)