From 2053489a1066d8181835cfb361610ae4bf6373e9 Mon Sep 17 00:00:00 2001 From: dlwjddus1112 Date: Thu, 9 Apr 2026 15:09:49 +0900 Subject: [PATCH 1/4] =?UTF-8?q?[Feat]=20#231=20=EC=98=A8=EB=B3=B4=EB=94=A9?= =?UTF-8?q?/=EC=95=BD=EA=B4=80=EB=8F=99=EC=9D=98=20=EC=97=AC=EB=B6=80=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=20=EC=9D=91=EB=8B=B5=20DTO=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../response/MemberCompletionResponse.java | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 src/main/java/org/sopt/kareer/domain/member/dto/response/MemberCompletionResponse.java diff --git a/src/main/java/org/sopt/kareer/domain/member/dto/response/MemberCompletionResponse.java b/src/main/java/org/sopt/kareer/domain/member/dto/response/MemberCompletionResponse.java new file mode 100644 index 0000000..ac7f5ee --- /dev/null +++ b/src/main/java/org/sopt/kareer/domain/member/dto/response/MemberCompletionResponse.java @@ -0,0 +1,20 @@ +package org.sopt.kareer.domain.member.dto.response; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Builder; + +@Builder +public record MemberCompletionResponse( + @Schema(description = "온보딩 여부") + boolean onboardingRequired, + + @Schema(description = "약관 동의 여부") + boolean agreeTerm +) { + public static MemberCompletionResponse of(boolean onboardingRequired, boolean agreeTerm){ + return MemberCompletionResponse.builder() + .onboardingRequired(onboardingRequired) + .agreeTerm(agreeTerm) + .build(); + } +} From b78a20f0752eea481df59ab394c1bccf401d8bf8 Mon Sep 17 00:00:00 2001 From: dlwjddus1112 Date: Thu, 9 Apr 2026 15:10:05 +0900 Subject: [PATCH 2/4] =?UTF-8?q?[Feat]=20#231=20=EC=98=A8=EB=B3=B4=EB=94=A9?= =?UTF-8?q?/=EC=95=BD=EA=B4=80=EB=8F=99=EC=9D=98=20=EC=97=AC=EB=B6=80=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=20=EB=A1=9C=EC=A7=81=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../member/controller/MemberController.java | 11 +++++ .../domain/member/service/MemberService.java | 19 ++++++-- .../swagger/SwaggerResponseDescription.java | 45 +++++++------------ 3 files changed, 42 insertions(+), 33 deletions(-) diff --git a/src/main/java/org/sopt/kareer/domain/member/controller/MemberController.java b/src/main/java/org/sopt/kareer/domain/member/controller/MemberController.java index affca4c..3345fb3 100644 --- a/src/main/java/org/sopt/kareer/domain/member/controller/MemberController.java +++ b/src/main/java/org/sopt/kareer/domain/member/controller/MemberController.java @@ -186,4 +186,15 @@ public ResponseEntity> agreeTerms( return ResponseEntity.status(HttpStatus.OK) .body(BaseResponse.ok("약관 동의 저장에 성공했습니다.")); } + + @Operation(summary = "온보딩, 약관동의 여부 조회") + @CustomExceptionDescription(GET_COMPLETION) + @GetMapping("completion") + public ResponseEntity> getMemberCompletionStatus( + @AuthenticationPrincipal Long memberId + ){ + return ResponseEntity.status(HttpStatus.OK) + .body(BaseResponse.ok(memberService.getCompletion(memberId), "온보딩/약관동의 여부 조회에 성공하였습니다,")); + } + } diff --git a/src/main/java/org/sopt/kareer/domain/member/service/MemberService.java b/src/main/java/org/sopt/kareer/domain/member/service/MemberService.java index 8672676..e97d4b8 100644 --- a/src/main/java/org/sopt/kareer/domain/member/service/MemberService.java +++ b/src/main/java/org/sopt/kareer/domain/member/service/MemberService.java @@ -1,21 +1,21 @@ package org.sopt.kareer.domain.member.service; import lombok.RequiredArgsConstructor; -import org.sopt.kareer.domain.member.dto.response.*; -import org.sopt.kareer.domain.member.entity.enums.*; -import org.sopt.kareer.domain.member.service.dto.request.MypageCommand; import org.sopt.kareer.domain.member.dto.request.MemberOnboardRequest; import org.sopt.kareer.domain.member.dto.request.MemberOnboardV2Request; import org.sopt.kareer.domain.member.dto.request.MemberTermsRequest; +import org.sopt.kareer.domain.member.dto.response.*; import org.sopt.kareer.domain.member.entity.Member; import org.sopt.kareer.domain.member.entity.MemberTerm; import org.sopt.kareer.domain.member.entity.MemberVisa; +import org.sopt.kareer.domain.member.entity.enums.LocalizedOnboardCategoryType; import org.sopt.kareer.domain.member.entity.enums.MemberStatus; import org.sopt.kareer.domain.member.exception.MemberErrorCode; import org.sopt.kareer.domain.member.exception.MemberException; import org.sopt.kareer.domain.member.repository.MemberRepository; import org.sopt.kareer.domain.member.repository.MemberTermRepository; import org.sopt.kareer.domain.member.repository.MemberVisaRepository; +import org.sopt.kareer.domain.member.service.dto.request.MypageCommand; import org.sopt.kareer.domain.member.util.PassportOcrParser; import org.sopt.kareer.domain.member.util.VisaOcrParser; import org.sopt.kareer.domain.term.entity.Term; @@ -308,4 +308,17 @@ public void agreeTerms(Long memberId, MemberTermsRequest request) { memberTermRepository.saveAll(memberTerms); } + + + public MemberCompletionResponse getCompletion(Long memberId){ + Member member = getById(memberId); + + MemberVisa memberVisa = memberVisaRepository.findActiveByMemberId(memberId) + .orElseThrow(() -> new MemberException(MemberErrorCode.VISA_NOT_FOUND)); + + boolean onboardingRequired = member.getStatus().equals(MemberStatus.PENDING); + boolean agreedTerm = memberTermRepository.existsByMemberIdAndAgreedTrue(memberId); + + return MemberCompletionResponse.of(onboardingRequired, agreedTerm); + } } diff --git a/src/main/java/org/sopt/kareer/global/config/swagger/SwaggerResponseDescription.java b/src/main/java/org/sopt/kareer/global/config/swagger/SwaggerResponseDescription.java index 7c05e16..30c3da1 100644 --- a/src/main/java/org/sopt/kareer/global/config/swagger/SwaggerResponseDescription.java +++ b/src/main/java/org/sopt/kareer/global/config/swagger/SwaggerResponseDescription.java @@ -1,39 +1,20 @@ package org.sopt.kareer.global.config.swagger; -import static org.sopt.kareer.domain.jobposting.exception.JobPostingErrorCode.JOB_POSTING_NOT_FOUND; -import static org.sopt.kareer.domain.jobposting.exception.JobPostingErrorCode.RESUME_CONTEXT_FAILED; -import static org.sopt.kareer.domain.jobposting.exception.JobPostingErrorCode.TOO_MANY_FILES; -import static org.sopt.kareer.domain.member.exception.MemberErrorCode.INVALID_COUNTRY; -import static org.sopt.kareer.domain.member.exception.MemberErrorCode.INVALID_VISA_POINT; -import static org.sopt.kareer.domain.member.exception.MemberErrorCode.MEMBER_NOT_FOUND; -import static org.sopt.kareer.domain.member.exception.MemberErrorCode.ONBOARDING_ALREADY_COMPLETED; -import static org.sopt.kareer.domain.member.exception.MemberErrorCode.ONBOARDING_REQUIRED; -import static org.sopt.kareer.domain.member.exception.MemberErrorCode.VISA_NOT_FOUND; -import static org.sopt.kareer.domain.roadmap.exception.RoadmapErrorCode.ACTION_ITEM_INACTIVE; -import static org.sopt.kareer.domain.roadmap.exception.RoadmapErrorCode.ACTION_ITEM_NOT_FOUND; -import static org.sopt.kareer.domain.roadmap.exception.RoadmapErrorCode.ACTION_ITEM_TYPE_BLANK; -import static org.sopt.kareer.domain.roadmap.exception.RoadmapErrorCode.ACTION_ITEM_TYPE_INVALID; -import static org.sopt.kareer.domain.roadmap.exception.RoadmapErrorCode.PHASE_ACTION_ALREADY_COMPLETED; -import static org.sopt.kareer.domain.roadmap.exception.RoadmapErrorCode.PHASE_ACTION_NOT_FOUND; -import static org.sopt.kareer.domain.roadmap.exception.RoadmapErrorCode.PHASE_ACTION_TYPE_BLANK; -import static org.sopt.kareer.domain.roadmap.exception.RoadmapErrorCode.PHASE_ACTION_TYPE_INVALID; -import static org.sopt.kareer.domain.roadmap.exception.RoadmapErrorCode.PHASE_NOT_FOUND; -import static org.sopt.kareer.domain.roadmap.exception.RoadmapErrorCode.PHASE_STATUS_BLANK; -import static org.sopt.kareer.domain.roadmap.exception.RoadmapErrorCode.PHASE_STATUS_INVALID; -import static org.sopt.kareer.domain.roadmap.exception.RoadmapErrorCode.TODO_ALREADY_ADDED; +import lombok.Getter; +import org.sopt.kareer.global.exception.errorcode.ErrorCode; +import org.sopt.kareer.global.exception.errorcode.GlobalErrorCode; + +import java.util.LinkedHashSet; +import java.util.Set; + +import static org.sopt.kareer.domain.jobposting.exception.JobPostingErrorCode.*; +import static org.sopt.kareer.domain.member.exception.MemberErrorCode.*; +import static org.sopt.kareer.domain.roadmap.exception.RoadmapErrorCode.*; import static org.sopt.kareer.domain.term.exception.TermErrorCode.*; import static org.sopt.kareer.global.auth.exception.AuthErrorCode.LOGIN_CODE_ALREADY_USED; import static org.sopt.kareer.global.auth.exception.AuthErrorCode.LOGIN_CODE_NOT_FOUND; import static org.sopt.kareer.global.external.ai.exception.LlmErrorCode.LLM_JSON_PARSING_FAILED; -import static org.sopt.kareer.global.external.ai.exception.RagErrorCode.DOCUMENTS_RETRIEVED_EMPTY; -import static org.sopt.kareer.global.external.ai.exception.RagErrorCode.EMBEDDING_FAILED; -import static org.sopt.kareer.global.external.ai.exception.RagErrorCode.EXTRACT_TEXT_FAILED; - -import java.util.LinkedHashSet; -import java.util.Set; -import lombok.Getter; -import org.sopt.kareer.global.exception.errorcode.ErrorCode; -import org.sopt.kareer.global.exception.errorcode.GlobalErrorCode; +import static org.sopt.kareer.global.external.ai.exception.RagErrorCode.*; @Getter public enum SwaggerResponseDescription { @@ -128,6 +109,10 @@ public enum SwaggerResponseDescription { DUPLICATE_TERM, MISSING_TERM, REQUIRED_TERM_NOT_AGREED + ))), + GET_COMPLETION(new LinkedHashSet<>(Set.of( + MEMBER_NOT_FOUND, + VISA_NOT_FOUND ))) ; From ce26391d69bfd4b08da4c68ff15c4b5732c2aa74 Mon Sep 17 00:00:00 2001 From: dlwjddus1112 Date: Thu, 9 Apr 2026 15:10:38 +0900 Subject: [PATCH 3/4] =?UTF-8?q?[Feat]=20#231=20OnboardingRestrictionFilter?= =?UTF-8?q?=EA=B0=80=20=EC=98=A8=EB=B3=B4=EB=94=A9/=EC=95=BD=EA=B4=80?= =?UTF-8?q?=EB=8F=99=EC=9D=98=20=EC=97=AC=EB=B6=80=20API=EB=8A=94=20?= =?UTF-8?q?=ED=86=B5=EA=B3=BC=ED=95=98=EB=8F=84=EB=A1=9D=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../global/security/filter/OnboardingRestrictionFilter.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/org/sopt/kareer/global/security/filter/OnboardingRestrictionFilter.java b/src/main/java/org/sopt/kareer/global/security/filter/OnboardingRestrictionFilter.java index a53ebf4..d99d04e 100644 --- a/src/main/java/org/sopt/kareer/global/security/filter/OnboardingRestrictionFilter.java +++ b/src/main/java/org/sopt/kareer/global/security/filter/OnboardingRestrictionFilter.java @@ -35,6 +35,7 @@ public class OnboardingRestrictionFilter extends OncePerRequestFilter { "/api/v1/members/roadmap/test", "/api/v1/terms", "/api/v1/members/term-agreements", + "/api/v1/members/completion", "/v3/api-docs/**" ); From 4e20eb588f743966bd22fd126bca20109954575d Mon Sep 17 00:00:00 2001 From: dlwjddus1112 Date: Thu, 9 Apr 2026 15:11:31 +0900 Subject: [PATCH 4/4] =?UTF-8?q?[Refactor]=20#231=20=EC=9C=A0=EC=A0=80=20?= =?UTF-8?q?=EC=83=81=ED=83=9C=20=EC=A1=B0=ED=9A=8C=EC=97=90=20=EC=98=A8?= =?UTF-8?q?=EB=B3=B4=EB=94=A9/=EC=95=BD=EA=B4=80=EB=8F=99=EC=9D=98=20?= =?UTF-8?q?=EC=97=AC=EB=B6=80=20=ED=95=84=EB=93=9C=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../member/dto/response/MemberStatusResponse.java | 12 ++---------- .../kareer/domain/member/service/MemberService.java | 5 +---- 2 files changed, 3 insertions(+), 14 deletions(-) diff --git a/src/main/java/org/sopt/kareer/domain/member/dto/response/MemberStatusResponse.java b/src/main/java/org/sopt/kareer/domain/member/dto/response/MemberStatusResponse.java index c36719d..756162f 100644 --- a/src/main/java/org/sopt/kareer/domain/member/dto/response/MemberStatusResponse.java +++ b/src/main/java/org/sopt/kareer/domain/member/dto/response/MemberStatusResponse.java @@ -20,23 +20,15 @@ public record MemberStatusResponse( LocalDate expectedGraduationDate, @Schema(description = "졸업일") - LocalDate graduationDate, - - @Schema(description = "온보딩 여부", example = "true") - boolean onboardingRequired, - - @Schema(description = "약관 동의 여부", example = "true") - boolean agreedTerm + LocalDate graduationDate ) { - public static MemberStatusResponse from(Member member, MemberVisa visa, boolean onboardingRequired, boolean agreedTerm) { + public static MemberStatusResponse from(Member member, MemberVisa visa) { return MemberStatusResponse.builder() .visaType(visa.getVisaType()) .visaExpiredAt(visa.getVisaExpiredAt()) .graduationDate(member.getGraduationDate()) .expectedGraduationDate(member.getExpectedGraduationDate()) - .onboardingRequired(onboardingRequired) - .agreedTerm(agreedTerm) .build(); } } diff --git a/src/main/java/org/sopt/kareer/domain/member/service/MemberService.java b/src/main/java/org/sopt/kareer/domain/member/service/MemberService.java index e97d4b8..3f95da4 100644 --- a/src/main/java/org/sopt/kareer/domain/member/service/MemberService.java +++ b/src/main/java/org/sopt/kareer/domain/member/service/MemberService.java @@ -177,10 +177,7 @@ public MemberStatusResponse getMemberStatus(Long memberId) { MemberVisa memberVisa = memberVisaRepository.findActiveByMemberId(memberId) .orElseThrow(() -> new MemberException(MemberErrorCode.VISA_NOT_FOUND)); - boolean onboardingRequired = member.getStatus().equals(MemberStatus.PENDING); - boolean agreedTerm = memberTermRepository.existsByMemberIdAndAgreedTrue(memberId); - - return MemberStatusResponse.from(member, memberVisa, onboardingRequired, agreedTerm); + return MemberStatusResponse.from(member, memberVisa); } public MypageResponse getMypage(Long memberId) {