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 @@ -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;
Expand Down Expand Up @@ -71,7 +68,7 @@ public ApiResponse<MockApplyCreateResponse> createActualApply(
) {
return ApiResponse.onSuccess(
"모의 서류 지원이 생성되었습니다.",
mockApplyService.createActualApply(getCurrentUser(userDetails), request.jobPostingId())
mockApplyService.createActualApply(userDetails.getUser(), request.jobPostingId())
);
}

Expand All @@ -95,7 +92,7 @@ public ApiResponse<MockApplyCreateResponse> 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(
Expand All @@ -109,11 +106,14 @@ public ApiResponse<MockApplyCreateResponse> 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\"}")
}
)
)
})
Expand All @@ -124,14 +124,7 @@ public ApiResponse<MockApplyCreateResponse> 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();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
import jakarta.validation.constraints.NotNull;

public record MockApplyCreateMockRequest(
@NotNull(message = "회사 ID는 필수입니다.")
Long companyId,

@NotNull(message = "소분류 ID는 필수입니다.")
Long detailClassificationId,

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -47,46 +43,35 @@ 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);

MockApply mockApply = MockApply.create(user, savedJobPosting, ApplyType.MOCK);
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 "";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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", "채용 공고 비동기 작업을 찾을 수 없습니다."),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
"",
Expand All @@ -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 경험 우대");
}

Expand All @@ -113,14 +116,34 @@ 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)
.extracting("code")
.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"));
}
Expand Down
Loading