diff --git a/src/main/java/com/jobdri/jobdri_api/domain/mockapply/controller/MockApplyController.java b/src/main/java/com/jobdri/jobdri_api/domain/mockapply/controller/MockApplyController.java index 011266c..cb97864 100644 --- a/src/main/java/com/jobdri/jobdri_api/domain/mockapply/controller/MockApplyController.java +++ b/src/main/java/com/jobdri/jobdri_api/domain/mockapply/controller/MockApplyController.java @@ -4,10 +4,7 @@ import com.jobdri.jobdri_api.domain.mockapply.dto.request.MockApplyCreateMockRequest; import com.jobdri.jobdri_api.domain.mockapply.dto.response.MockApplyCreateResponse; import com.jobdri.jobdri_api.domain.mockapply.service.MockApplyService; -import com.jobdri.jobdri_api.domain.user.entity.User; import com.jobdri.jobdri_api.global.apiPayload.ApiResponse; -import com.jobdri.jobdri_api.global.apiPayload.code.GeneralErrorCode; -import com.jobdri.jobdri_api.global.apiPayload.exception.GeneralException; import com.jobdri.jobdri_api.global.security.UserDetailsImpl; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; @@ -71,7 +68,7 @@ public ApiResponse createActualApply( ) { return ApiResponse.onSuccess( "모의 서류 지원이 생성되었습니다.", - mockApplyService.createActualApply(getCurrentUser(userDetails), request.jobPostingId()) + mockApplyService.createActualApply(userDetails.getUser(), request.jobPostingId()) ); } @@ -95,7 +92,7 @@ public ApiResponse createActualApply( content = @Content( mediaType = "application/json", schema = @Schema(implementation = ApiResponse.class), - examples = @ExampleObject(value = "{\"isSuccess\":false,\"code\":\"REQ_4002\",\"message\":\"파라미터 형식이 잘못되었습니다.\",\"result\":null,\"error\":[\"[detailClassificationId] 소분류 ID는 필수입니다. (입력값: null)\"]}") + examples = @ExampleObject(value = "{\"isSuccess\":false,\"code\":\"REQ_4002\",\"message\":\"파라미터 형식이 잘못되었습니다.\",\"result\":null,\"error\":[\"[companyId] 회사 ID는 필수입니다. (입력값: null)\"]}") ) ), @io.swagger.v3.oas.annotations.responses.ApiResponse( @@ -109,11 +106,14 @@ public ApiResponse createActualApply( ), @io.swagger.v3.oas.annotations.responses.ApiResponse( responseCode = "404", - description = "소분류 없음", + description = "회사 또는 소분류 없음", content = @Content( mediaType = "application/json", schema = @Schema(implementation = ApiResponse.class), - examples = @ExampleObject(value = "{\"isSuccess\":false,\"code\":\"CLASSIFICATION_4041\",\"message\":\"해당 소분류를 찾을 수 없습니다. detailClassificationId=999\",\"result\":null,\"error\":\"해당 소분류를 찾을 수 없습니다. detailClassificationId=999\"}") + examples = { + @ExampleObject(name = "company_not_found", value = "{\"isSuccess\":false,\"code\":\"COMPANY_4041\",\"message\":\"해당 회사를 찾을 수 없습니다. companyId=999\",\"result\":null,\"error\":\"해당 회사를 찾을 수 없습니다. companyId=999\"}"), + @ExampleObject(name = "classification_not_found", value = "{\"isSuccess\":false,\"code\":\"CLASSIFICATION_4041\",\"message\":\"해당 소분류를 찾을 수 없습니다. detailClassificationId=999\",\"result\":null,\"error\":\"해당 소분류를 찾을 수 없습니다. detailClassificationId=999\"}") + } ) ) }) @@ -124,14 +124,7 @@ public ApiResponse createMockApply( ) { return ApiResponse.onSuccess( "모의 서류 지원이 생성되었습니다.", - mockApplyService.createMockApply(getCurrentUser(userDetails), request) + mockApplyService.createMockApply(userDetails.getUser(), request) ); } - - private User getCurrentUser(UserDetailsImpl userDetails) { - if (userDetails == null) { - throw new GeneralException(GeneralErrorCode.MISSING_AUTH_INFO); - } - return userDetails.getUser(); - } } diff --git a/src/main/java/com/jobdri/jobdri_api/domain/mockapply/dto/request/MockApplyCreateMockRequest.java b/src/main/java/com/jobdri/jobdri_api/domain/mockapply/dto/request/MockApplyCreateMockRequest.java index 3ed547e..2cc169e 100644 --- a/src/main/java/com/jobdri/jobdri_api/domain/mockapply/dto/request/MockApplyCreateMockRequest.java +++ b/src/main/java/com/jobdri/jobdri_api/domain/mockapply/dto/request/MockApplyCreateMockRequest.java @@ -3,6 +3,9 @@ import jakarta.validation.constraints.NotNull; public record MockApplyCreateMockRequest( + @NotNull(message = "회사 ID는 필수입니다.") + Long companyId, + @NotNull(message = "소분류 ID는 필수입니다.") Long detailClassificationId, diff --git a/src/main/java/com/jobdri/jobdri_api/domain/mockapply/service/MockApplyService.java b/src/main/java/com/jobdri/jobdri_api/domain/mockapply/service/MockApplyService.java index 9a16b5b..59314eb 100644 --- a/src/main/java/com/jobdri/jobdri_api/domain/mockapply/service/MockApplyService.java +++ b/src/main/java/com/jobdri/jobdri_api/domain/mockapply/service/MockApplyService.java @@ -3,7 +3,6 @@ import com.jobdri.jobdri_api.domain.classification.entity.DetailClassification; import com.jobdri.jobdri_api.domain.classification.repository.DetailClassificationRepository; import com.jobdri.jobdri_api.domain.company.entity.Company; -import com.jobdri.jobdri_api.domain.company.entity.CompanySize; import com.jobdri.jobdri_api.domain.company.repository.CompanyRepository; import com.jobdri.jobdri_api.domain.jobposting.entity.JobPosting; import com.jobdri.jobdri_api.domain.jobposting.repository.JobPostingRepository; @@ -25,9 +24,6 @@ @Transactional(readOnly = true) public class MockApplyService { - private static final String VIRTUAL_COMPANY_NAME = "가상 기업"; - private static final CompanySize VIRTUAL_COMPANY_SIZE = CompanySize.STARTUP; - private final MockApplyRepository mockApplyRepository; private final JobPostingRepository jobPostingRepository; private final DetailClassificationRepository detailClassificationRepository; @@ -47,21 +43,24 @@ public MockApplyCreateResponse createActualApply(User user, Long jobPostingId) { @Transactional public MockApplyCreateResponse createMockApply(User user, MockApplyCreateMockRequest request) { + Company company = companyRepository.findById(request.companyId()) + .orElseThrow(() -> new GeneralException( + GeneralErrorCode.COMPANY_NOT_FOUND, + "해당 회사를 찾을 수 없습니다. companyId=" + request.companyId() + )); + DetailClassification detailClassification = detailClassificationRepository.findById(request.detailClassificationId()) .orElseThrow(() -> new GeneralException( GeneralErrorCode.CLASSIFICATION_NOT_FOUND, "해당 소분류를 찾을 수 없습니다. detailClassificationId=" + request.detailClassificationId() )); - Company company = companyRepository.findByName(VIRTUAL_COMPANY_NAME) - .orElseGet(() -> companyRepository.save(Company.create(VIRTUAL_COMPANY_NAME, VIRTUAL_COMPANY_SIZE))); - JobPosting jobPosting = JobPosting.create( company, detailClassification, - resolveTask(request.task(), detailClassification), - resolveRequirement(request.requirement(), detailClassification), - resolvePreferred(request.preferred(), detailClassification) + normalizeText(request.task()), + normalizeText(request.requirement()), + normalizeText(request.preferred()) ); JobPosting savedJobPosting = jobPostingRepository.save(jobPosting); @@ -69,24 +68,10 @@ public MockApplyCreateResponse createMockApply(User user, MockApplyCreateMockReq return MockApplyCreateResponse.from(mockApplyRepository.save(mockApply)); } - private String resolveTask(String task, DetailClassification detailClassification) { - if (StringUtils.hasText(task)) { - return task; - } - return detailClassification.getDetailName() + " 직무 기반 가상 주요 업무를 수행합니다."; - } - - private String resolveRequirement(String requirement, DetailClassification detailClassification) { - if (StringUtils.hasText(requirement)) { - return requirement; - } - return detailClassification.getDetailName() + " 직무 수행에 필요한 기본 자격 요건을 갖춥니다."; - } - - private String resolvePreferred(String preferred, DetailClassification detailClassification) { - if (StringUtils.hasText(preferred)) { - return preferred; + private String normalizeText(String value) { + if (StringUtils.hasText(value)) { + return value; } - return detailClassification.getDetailName() + " 직무 관련 경험과 역량을 우대합니다."; + return ""; } } diff --git a/src/main/java/com/jobdri/jobdri_api/global/apiPayload/code/GeneralErrorCode.java b/src/main/java/com/jobdri/jobdri_api/global/apiPayload/code/GeneralErrorCode.java index a81e266..c528607 100644 --- a/src/main/java/com/jobdri/jobdri_api/global/apiPayload/code/GeneralErrorCode.java +++ b/src/main/java/com/jobdri/jobdri_api/global/apiPayload/code/GeneralErrorCode.java @@ -32,6 +32,9 @@ public enum GeneralErrorCode implements BaseErrorCode { // 분류 에러 CLASSIFICATION_NOT_FOUND(HttpStatus.NOT_FOUND, "CLASSIFICATION_4041", "분류를 찾을 수 없습니다."), + // 회사 에러 + COMPANY_NOT_FOUND(HttpStatus.NOT_FOUND, "COMPANY_4041", "회사를 찾을 수 없습니다."), + // 채용 공고 에러 JOB_POSTING_NOT_FOUND(HttpStatus.NOT_FOUND, "JOB_POSTING_4041", "채용 공고를 찾을 수 없습니다."), JOB_POSTING_ASYNC_TASK_NOT_FOUND(HttpStatus.NOT_FOUND, "JOB_POSTING_4042", "채용 공고 비동기 작업을 찾을 수 없습니다."), diff --git a/src/test/java/com/jobdri/jobdri_api/domain/mockapply/service/MockApplyServiceTest.java b/src/test/java/com/jobdri/jobdri_api/domain/mockapply/service/MockApplyServiceTest.java index c175bb2..efd1649 100644 --- a/src/test/java/com/jobdri/jobdri_api/domain/mockapply/service/MockApplyServiceTest.java +++ b/src/test/java/com/jobdri/jobdri_api/domain/mockapply/service/MockApplyServiceTest.java @@ -75,8 +75,10 @@ void createActualApply() { @DisplayName("소분류를 기준으로 가상 공고와 MOCK 타입 모의 서류 지원을 생성한다") void createMockApply() { User user = saveUser("mock-apply@example.com"); + Company company = companyRepository.save(Company.create("선택 기업", CompanySize.MEDIUM)); DetailClassification detailClassification = saveDetailClassification("프론트엔드 개발"); MockApplyCreateMockRequest request = new MockApplyCreateMockRequest( + company.getId(), detailClassification.getId(), null, "", @@ -90,11 +92,12 @@ void createMockApply() { assertThat(response.applyType()).isEqualTo(ApplyType.MOCK); assertThat(mockApply.getUser().getId()).isEqualTo(user.getId()); assertThat(mockApply.getApplyType()).isEqualTo(ApplyType.MOCK); - assertThat(jobPosting.getCompany().getName()).isEqualTo("가상 기업"); - assertThat(jobPosting.getCompany().getSize()).isEqualTo(CompanySize.STARTUP); + assertThat(jobPosting.getCompany().getId()).isEqualTo(company.getId()); + assertThat(jobPosting.getCompany().getName()).isEqualTo("선택 기업"); + assertThat(jobPosting.getCompany().getSize()).isEqualTo(CompanySize.MEDIUM); assertThat(jobPosting.getDetailClassification().getId()).isEqualTo(detailClassification.getId()); - assertThat(jobPosting.getTask()).contains("프론트엔드 개발"); - assertThat(jobPosting.getRequirement()).contains("프론트엔드 개발"); + assertThat(jobPosting.getTask()).isEmpty(); + assertThat(jobPosting.getRequirement()).isEmpty(); assertThat(jobPosting.getPreferred()).isEqualTo("React 경험 우대"); } @@ -113,7 +116,8 @@ void createActualApplyThrowsWhenJobPostingNotFound() { @DisplayName("존재하지 않는 소분류 ID로 MOCK 타입 지원 생성 시 예외를 던진다") void createMockApplyThrowsWhenDetailClassificationNotFound() { User user = saveUser("missing-detail-classification@example.com"); - MockApplyCreateMockRequest request = new MockApplyCreateMockRequest(9999L, null, null, null); + Company company = companyRepository.save(Company.create("선택 기업", CompanySize.MEDIUM)); + MockApplyCreateMockRequest request = new MockApplyCreateMockRequest(company.getId(), 9999L, null, null, null); assertThatThrownBy(() -> mockApplyService.createMockApply(user, request)) .isInstanceOf(GeneralException.class) @@ -121,6 +125,25 @@ void createMockApplyThrowsWhenDetailClassificationNotFound() { .isEqualTo(GeneralErrorCode.CLASSIFICATION_NOT_FOUND); } + @Test + @DisplayName("존재하지 않는 회사 ID로 MOCK 타입 지원 생성 시 예외를 던진다") + void createMockApplyThrowsWhenCompanyNotFound() { + User user = saveUser("missing-company@example.com"); + DetailClassification detailClassification = saveDetailClassification("데이터 분석"); + MockApplyCreateMockRequest request = new MockApplyCreateMockRequest( + 9999L, + detailClassification.getId(), + null, + null, + null + ); + + assertThatThrownBy(() -> mockApplyService.createMockApply(user, request)) + .isInstanceOf(GeneralException.class) + .extracting("code") + .isEqualTo(GeneralErrorCode.COMPANY_NOT_FOUND); + } + private User saveUser(String email) { return userRepository.save(User.signup("테스트 사용자", email, "encoded-password")); }