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
@@ -0,0 +1,115 @@
package com.jobdri.jobdri_api.domain.classification.controller;

import com.jobdri.jobdri_api.domain.classification.dto.response.ClassificationLowerResponseDto;
import com.jobdri.jobdri_api.domain.classification.dto.response.ClassificationResponseDto;
import com.jobdri.jobdri_api.domain.classification.service.ClassificationService;
import com.jobdri.jobdri_api.global.apiPayload.ApiResponse;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.ExampleObject;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/classifications")
@Tag(name = "Classification", description = "직무 분류 조회 API")
public class ClassificationController {

private final ClassificationService classificationService;

@Operation(
summary = "대분류 전체 조회",
description = "등록된 모든 대분류(Big Classification)를 전체 조회합니다."
)
@ApiResponses(value = {
@io.swagger.v3.oas.annotations.responses.ApiResponse(
responseCode = "200",
description = "대분류 조회 성공",
content = @Content(
mediaType = "application/json",
schema = @Schema(implementation = ApiResponse.class),
examples = @ExampleObject(value = "{\"isSuccess\":true,\"code\":\"COMMON2000\",\"message\":\"대분류 조회에 성공했습니다.\",\"result\":[{\"classificationId\":1,\"classificationName\":\"개발\"},{\"classificationId\":2,\"classificationName\":\"디자인\"}],\"error\":null}")
)
)
})
@GetMapping
public ApiResponse<List<ClassificationResponseDto>> getBigClassifications() {
return ApiResponse.onSuccess(
"대분류 조회에 성공했습니다.",
classificationService.getBigClassifications()
);
}

@Operation(
summary = "대분류 기준 중분류 조회",
description = "대분류 ID를 기준으로 연결된 모든 중분류(Middle Classification)를 조회합니다."
)
@ApiResponses(value = {
@io.swagger.v3.oas.annotations.responses.ApiResponse(
responseCode = "200",
description = "중분류 조회 성공",
content = @Content(
mediaType = "application/json",
schema = @Schema(implementation = ApiResponse.class),
examples = @ExampleObject(value = "{\"isSuccess\":true,\"code\":\"COMMON2000\",\"message\":\"중분류 조회에 성공했습니다.\",\"result\":{\"upperClassId\":1,\"upperClassName\":\"개발\",\"lowerClassifications\":[{\"classificationId\":10,\"classificationName\":\"백엔드\"},{\"classificationId\":11,\"classificationName\":\"프론트엔드\"}]},\"error\":null}")
)
),
@io.swagger.v3.oas.annotations.responses.ApiResponse(
responseCode = "404",
description = "대분류를 찾을 수 없음",
content = @Content(
mediaType = "application/json",
schema = @Schema(implementation = ApiResponse.class),
examples = @ExampleObject(value = "{\"isSuccess\":false,\"code\":\"CLASSIFICATION_4041\",\"message\":\"분류를 찾을 수 없습니다.\",\"result\":null,\"error\":\"해당 대분류를 찾을 수 없습니다. bigId=999\"}")
)
)
})
@GetMapping("/{bigId}/middles")
public ApiResponse<ClassificationLowerResponseDto> getMiddleClassifications(@PathVariable Long bigId) {
return ApiResponse.onSuccess(
"중분류 조회에 성공했습니다.",
classificationService.getMiddleClassifications(bigId)
);
}

@Operation(
summary = "중분류 기준 소분류 조회",
description = "중분류 ID를 기준으로 연결된 모든 소분류(Detail Classification)를 조회합니다."
)
@ApiResponses(value = {
@io.swagger.v3.oas.annotations.responses.ApiResponse(
responseCode = "200",
description = "소분류 조회 성공",
content = @Content(
mediaType = "application/json",
schema = @Schema(implementation = ApiResponse.class),
examples = @ExampleObject(value = "{\"isSuccess\":true,\"code\":\"COMMON2000\",\"message\":\"소분류 조회에 성공했습니다.\",\"result\":{\"upperClassId\":10,\"upperClassName\":\"백엔드\",\"lowerClassifications\":[{\"classificationId\":100,\"classificationName\":\"Java/Spring\"},{\"classificationId\":101,\"classificationName\":\"Node.js\"}]},\"error\":null}")
)
),
@io.swagger.v3.oas.annotations.responses.ApiResponse(
responseCode = "404",
description = "중분류를 찾을 수 없음",
content = @Content(
mediaType = "application/json",
schema = @Schema(implementation = ApiResponse.class),
examples = @ExampleObject(value = "{\"isSuccess\":false,\"code\":\"CLASSIFICATION_4041\",\"message\":\"분류를 찾을 수 없습니다.\",\"result\":null,\"error\":\"해당 중분류를 찾을 수 없습니다. middleId=999\"}")
)
)
})
@GetMapping("/middles/{middleId}/details")
public ApiResponse<ClassificationLowerResponseDto> getDetailClassifications(@PathVariable Long middleId) {
return ApiResponse.onSuccess(
"소분류 조회에 성공했습니다.",
classificationService.getDetailClassifications(middleId)
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.jobdri.jobdri_api.domain.classification.dto.response;

import java.util.List;

public record ClassificationLowerResponseDto(Long upperClassId,
String upperClassName,
List<ClassificationResponseDto> lowerClassifications) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package com.jobdri.jobdri_api.domain.classification.dto.response;

public record ClassificationResponseDto(Long classificationId, String classificationName) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package com.jobdri.jobdri_api.domain.classification.service;

import com.jobdri.jobdri_api.domain.classification.dto.response.ClassificationLowerResponseDto;
import com.jobdri.jobdri_api.domain.classification.dto.response.ClassificationResponseDto;
import com.jobdri.jobdri_api.domain.classification.entity.Classification;
import com.jobdri.jobdri_api.domain.classification.entity.MiddleClassification;
import com.jobdri.jobdri_api.domain.classification.repository.ClassificationRepository;
import com.jobdri.jobdri_api.domain.classification.repository.DetailClassificationRepository;
import com.jobdri.jobdri_api.domain.classification.repository.MiddleClassificationRepository;
import com.jobdri.jobdri_api.global.apiPayload.code.GeneralErrorCode;
import com.jobdri.jobdri_api.global.apiPayload.exception.GeneralException;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class ClassificationService {

private final ClassificationRepository classificationRepository;
private final DetailClassificationRepository detailClassificationRepository;
private final MiddleClassificationRepository middleClassificationRepository;

public List<ClassificationResponseDto> getBigClassifications() {
return classificationRepository.findAll().stream()
.map(classification -> new ClassificationResponseDto(
classification.getId(),
classification.getBigName()
))
.toList();
}

public ClassificationLowerResponseDto getMiddleClassifications(Long bigId) {
Classification classification = classificationRepository.findById(bigId)
.orElseThrow(() -> new GeneralException(
GeneralErrorCode.CLASSIFICATION_NOT_FOUND,
"해당 대분류를 찾을 수 없습니다. bigId=" + bigId
));

List<ClassificationResponseDto> middleClassifications = middleClassificationRepository
.findAllByClassificationId(bigId).stream()
.map(middleClassification -> new ClassificationResponseDto(
middleClassification.getId(),
middleClassification.getMiddleName()
))
.toList();

return new ClassificationLowerResponseDto(
classification.getId(),
classification.getBigName(),
middleClassifications
);
}

public ClassificationLowerResponseDto getDetailClassifications(Long middleId) {
MiddleClassification middleClassification = middleClassificationRepository.findById(middleId)
.orElseThrow(() -> new GeneralException(
GeneralErrorCode.CLASSIFICATION_NOT_FOUND,
"해당 중분류를 찾을 수 없습니다. middleId=" + middleId
));

List<ClassificationResponseDto> detailClassifications = detailClassificationRepository
.findAllByMiddleClassificationId(middleId).stream()
.map(detailClassification -> new ClassificationResponseDto(
detailClassification.getId(),
detailClassification.getDetailName()
))
.toList();

return new ClassificationLowerResponseDto(
middleClassification.getId(),
middleClassification.getMiddleName(),
detailClassifications
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ public enum GeneralErrorCode implements BaseErrorCode {
INVALID_PARAMETER(HttpStatus.BAD_REQUEST, "REQ_4002", "파라미터 형식이 잘못되었습니다."),
UNSUPPORTED_CONTENT_TYPE(HttpStatus.UNSUPPORTED_MEDIA_TYPE, "REQ_4151", "지원하지 않는 Content-Type입니다."),

// 분류 에러
CLASSIFICATION_NOT_FOUND(HttpStatus.NOT_FOUND, "CLASSIFICATION_4041", "분류를 찾을 수 없습니다."),

// 유저 에러
USER_NOT_FOUND(HttpStatus.NOT_FOUND, "USER_4041", "유저를 찾을 수 없습니다.");

Expand Down
Loading