diff --git a/src/main/java/UMC/career_mate/domain/content/service/ContentService.java b/src/main/java/UMC/career_mate/domain/content/service/ContentService.java index 4539a4c..516b189 100644 --- a/src/main/java/UMC/career_mate/domain/content/service/ContentService.java +++ b/src/main/java/UMC/career_mate/domain/content/service/ContentService.java @@ -72,6 +72,11 @@ public PageResponseDTO> getContentsByJobId(int page, in .toList(); boolean hasNext = contentPage.hasNext(); - return new PageResponseDTO<>(page, hasNext, contentList); + + return PageResponseDTO.>builder() + .page(page) + .hasNext(hasNext) + .result(contentList) + .build(); } } \ No newline at end of file diff --git a/src/main/java/UMC/career_mate/domain/contentScrap/service/ContentScrapService.java b/src/main/java/UMC/career_mate/domain/contentScrap/service/ContentScrapService.java index b44d121..786f853 100644 --- a/src/main/java/UMC/career_mate/domain/contentScrap/service/ContentScrapService.java +++ b/src/main/java/UMC/career_mate/domain/contentScrap/service/ContentScrapService.java @@ -59,6 +59,10 @@ public PageResponseDTO> getScrapContents(Member me .map(ContentScrapConverter::toContentScrapResponseDTO) .toList(); - return new PageResponseDTO<>(page, scraps.hasNext(), contentList); + return PageResponseDTO.>builder() + .page(page) + .hasNext(scraps.hasNext()) + .result(contentList) + .build(); } } \ No newline at end of file diff --git a/src/main/java/UMC/career_mate/domain/member/service/MemberService.java b/src/main/java/UMC/career_mate/domain/member/service/MemberService.java index 3d63b97..eefa65f 100644 --- a/src/main/java/UMC/career_mate/domain/member/service/MemberService.java +++ b/src/main/java/UMC/career_mate/domain/member/service/MemberService.java @@ -1,5 +1,7 @@ package UMC.career_mate.domain.member.service; +import UMC.career_mate.domain.chatgpt.GptAnswer; +import UMC.career_mate.domain.chatgpt.repository.GptAnswerRepository; import UMC.career_mate.domain.job.Job; import UMC.career_mate.domain.job.Service.JobService; import UMC.career_mate.domain.member.Member; @@ -8,10 +10,11 @@ import UMC.career_mate.domain.member.dto.response.MemberInfoDTO; import UMC.career_mate.domain.member.enums.SocialType; import UMC.career_mate.domain.member.repository.MemberRepository; -import UMC.career_mate.domain.planner.dto.request.CreatePlannerDTO; import UMC.career_mate.domain.planner.service.PlannerCommandService; +import UMC.career_mate.domain.recruit.enums.RecruitKeyword; import UMC.career_mate.global.response.exception.GeneralException; import UMC.career_mate.global.response.exception.code.CommonErrorCode; +import java.util.Optional; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -26,6 +29,7 @@ public class MemberService { private final MemberRepository memberRepository; private final JobService jobService; private final PlannerCommandService plannerService; + private final GptAnswerRepository gptAnswerRepository; @Transactional public Member makeProfile(CreateProfileDTO request,Member member) { @@ -77,9 +81,17 @@ public Member findMemberByIdAndClientId(Long memberId, String clientId) { @Transactional public Member changeProfile(Long memberId, CreateProfileDTO request) { Member member = findMemberByMemberId(memberId); + Job beforeJob = member.getJob(); Job job = jobService.findJobById(request.job()); member.createProfile(request, job); + if (!beforeJob.getId().equals(job.getId())) { + gptAnswerRepository.findByMember(member).ifPresent( + gptAnswer -> gptAnswer.updateData( + RecruitKeyword.getRecruitKeywordFromProfileJob(job), 0) + ); + } + return member; } } \ No newline at end of file diff --git a/src/main/java/UMC/career_mate/domain/recruit/controller/RecruitController.java b/src/main/java/UMC/career_mate/domain/recruit/controller/RecruitController.java index 5a911ea..1b36018 100644 --- a/src/main/java/UMC/career_mate/domain/recruit/controller/RecruitController.java +++ b/src/main/java/UMC/career_mate/domain/recruit/controller/RecruitController.java @@ -1,7 +1,7 @@ package UMC.career_mate.domain.recruit.controller; import UMC.career_mate.domain.member.Member; -import UMC.career_mate.domain.recruit.dto.response.RecommendRecruitDTO; +import UMC.career_mate.domain.recruit.dto.response.RecommendRecruitsDTO; import UMC.career_mate.domain.recruit.dto.response.RecruitInfoDTO; import UMC.career_mate.domain.recruit.enums.JobCode; import UMC.career_mate.domain.recruit.enums.RecruitSortType; @@ -11,7 +11,6 @@ import UMC.career_mate.global.common.PageResponseDTO; import UMC.career_mate.global.response.ApiResponse; import io.swagger.v3.oas.annotations.Operation; -import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; @@ -41,7 +40,7 @@ public class RecruitController { 마감 늦은 순 -> DEADLINE_DESC """) @GetMapping - public ApiResponse>> getRecommendRecruitList( + public ApiResponse> getRecommendRecruitList( @RequestParam(defaultValue = "1", required = false) int page, @RequestParam(defaultValue = "6", required = false) int size, @RequestParam(defaultValue = "POSTING_DESC", required = false) RecruitSortType recruitSortType, diff --git a/src/main/java/UMC/career_mate/domain/recruit/converter/RecruitConverter.java b/src/main/java/UMC/career_mate/domain/recruit/converter/RecruitConverter.java index 1065363..4ad43b0 100644 --- a/src/main/java/UMC/career_mate/domain/recruit/converter/RecruitConverter.java +++ b/src/main/java/UMC/career_mate/domain/recruit/converter/RecruitConverter.java @@ -5,7 +5,8 @@ import UMC.career_mate.domain.recruit.dto.FilterConditionDTO; import UMC.career_mate.domain.recruit.dto.MemberTemplateAnswerDTO; import UMC.career_mate.domain.recruit.dto.api.SaraminResponseDTO.Job; -import UMC.career_mate.domain.recruit.dto.response.RecommendRecruitDTO; +import UMC.career_mate.domain.recruit.dto.response.RecommendRecruitsDTO; +import UMC.career_mate.domain.recruit.dto.response.RecommendRecruitsDTO.RecruitThumbNailInfoDTO; import UMC.career_mate.domain.recruit.dto.response.RecruitInfoDTO; import UMC.career_mate.domain.recruit.enums.EducationLevel; import UMC.career_mate.domain.recruit.enums.RecruitKeyword; @@ -15,6 +16,7 @@ import java.time.ZoneId; import java.time.temporal.ChronoUnit; import java.util.Arrays; +import java.util.List; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringEscapeUtils; @@ -51,8 +53,15 @@ public static Recruit toRecruit(Job job, String recruitUrl, String companyInfoUr .build(); } - public static RecommendRecruitDTO toRecommendRecruitDTO(Recruit recruit, boolean isScraped) { - return RecommendRecruitDTO.builder() + public static RecommendRecruitsDTO toRecommendRecruitsDTO(Member member, List recruitThumbNailInfoDTOList) { + return RecommendRecruitsDTO.builder() + .jobName(member.getJob().getName()) + .recruitThumbNailInfoDTOList(recruitThumbNailInfoDTOList) + .build(); + } + + public static RecruitThumbNailInfoDTO toRecruitThumbNailInfoDTO(Recruit recruit, boolean isScraped) { + return RecruitThumbNailInfoDTO.builder() .recruitId(recruit.getId()) .companyName(recruit.getCompanyName()) .title(recruit.getTitle()) diff --git a/src/main/java/UMC/career_mate/domain/recruit/dto/response/RecommendRecruitDTO.java b/src/main/java/UMC/career_mate/domain/recruit/dto/response/RecommendRecruitDTO.java deleted file mode 100644 index 7d86844..0000000 --- a/src/main/java/UMC/career_mate/domain/recruit/dto/response/RecommendRecruitDTO.java +++ /dev/null @@ -1,26 +0,0 @@ -package UMC.career_mate.domain.recruit.dto.response; - -import java.time.LocalDateTime; -import lombok.Builder; - -@Builder -public record RecommendRecruitDTO( - Long recruitId, - String companyName, - String title, - String deadLine, - boolean isScraped, - - /** - * TODO: 아래로는 (필터링, 정렬) 잘 되는지 확인용 데이터, 나중에 삭제 예정 - */ - Integer experienceLevelCode, // 경력 코드 : 0(경력무관), 1(신입), 2(경력), 3(신입/경력) - Integer experienceLevelMin, // 경력 년수 최소 값 - Integer experienceLevelMax, // 경력 년수 최대 값 - String experienceLevelName, - Integer educationLevelCode, // 학력 코드 0(학력무관), 1(고등학교졸업), 2(대학졸업(2,3년)), 3(대학졸업(4년)), 4(석사졸업), 5(박사졸업) 등 - String educationLevelName, - LocalDateTime postingDate -) { - -} diff --git a/src/main/java/UMC/career_mate/domain/recruit/dto/response/RecommendRecruitsDTO.java b/src/main/java/UMC/career_mate/domain/recruit/dto/response/RecommendRecruitsDTO.java new file mode 100644 index 0000000..1e32c74 --- /dev/null +++ b/src/main/java/UMC/career_mate/domain/recruit/dto/response/RecommendRecruitsDTO.java @@ -0,0 +1,35 @@ +package UMC.career_mate.domain.recruit.dto.response; + +import java.time.LocalDateTime; +import java.util.List; +import lombok.Builder; + +@Builder +public record RecommendRecruitsDTO( + String jobName, + List recruitThumbNailInfoDTOList +) { + + @Builder + public record RecruitThumbNailInfoDTO( + Long recruitId, + String companyName, + String title, + String deadLine, + boolean isScraped, + + /** + * TODO: 아래로는 (필터링, 정렬) 잘 되는지 확인용 데이터, 나중에 삭제 예정 + */ + Integer experienceLevelCode, // 경력 코드 : 0(경력무관), 1(신입), 2(경력), 3(신입/경력) + Integer experienceLevelMin, // 경력 년수 최소 값 + Integer experienceLevelMax, // 경력 년수 최대 값 + String experienceLevelName, + Integer educationLevelCode, // 학력 코드 0(학력무관), 1(고등학교졸업), 2(대학졸업(2,3년)), 3(대학졸업(4년)), 4(석사졸업), 5(박사졸업) 등 + String educationLevelName, + LocalDateTime postingDate + ) { + + } + +} diff --git a/src/main/java/UMC/career_mate/domain/recruit/repository/querydsl/RecruitQueryRepositoryImpl.java b/src/main/java/UMC/career_mate/domain/recruit/repository/querydsl/RecruitQueryRepositoryImpl.java index 40142c0..8823f5c 100644 --- a/src/main/java/UMC/career_mate/domain/recruit/repository/querydsl/RecruitQueryRepositoryImpl.java +++ b/src/main/java/UMC/career_mate/domain/recruit/repository/querydsl/RecruitQueryRepositoryImpl.java @@ -54,10 +54,16 @@ public Page findByKeywordWithBooleanBuilder(RecruitKeyword recruitKeywo .where(builder) .orderBy(createOrderSpecifier(recruitSortType)) .offset(pageable.getOffset()) - .limit(pageable.getPageSize() + 1) + .limit(pageable.getPageSize()) .fetch(); - return new PageImpl<>(result); + Long total = queryFactory + .select(recruit.count()) + .from(recruit) + .where(builder) + .fetchOne(); + + return new PageImpl<>(result, pageable, total); } private void filterIncludeKeywordList(List includekeywordList, BooleanBuilder builder) { diff --git a/src/main/java/UMC/career_mate/domain/recruit/service/RecruitQueryService.java b/src/main/java/UMC/career_mate/domain/recruit/service/RecruitQueryService.java index 1c61ef4..1f4efc7 100644 --- a/src/main/java/UMC/career_mate/domain/recruit/service/RecruitQueryService.java +++ b/src/main/java/UMC/career_mate/domain/recruit/service/RecruitQueryService.java @@ -12,7 +12,7 @@ import UMC.career_mate.domain.member.Member; import UMC.career_mate.domain.recruit.Recruit; import UMC.career_mate.domain.recruit.converter.RecruitConverter; -import UMC.career_mate.domain.recruit.dto.response.RecommendRecruitDTO; +import UMC.career_mate.domain.recruit.dto.response.RecommendRecruitsDTO; import UMC.career_mate.domain.recruit.dto.response.RecruitInfoDTO; import UMC.career_mate.domain.recruit.enums.EducationLevel; import UMC.career_mate.domain.recruit.enums.RecruitKeyword; @@ -60,7 +60,7 @@ public class RecruitQueryService { private final static String INTERN_QUESTION_CONTENT_PERIOD = "근무기간"; private final static String TEMPLATE_ANSWER_IS_NULL_OR_EMPTY_COMMENT = "프로젝트 또는 인턴 템플릿에 대해 답변을 작성하고, Chat GPT의 코멘트를 받아보세요!"; - public PageResponseDTO> getRecommendRecruitList(int page, int size, + public PageResponseDTO getRecommendRecruitList(int page, int size, RecruitSortType recruitSortType, Member member) { FilterConditionDTO filterCondition = createFilterCondition(member); @@ -74,7 +74,7 @@ public PageResponseDTO> getRecommendRecruitList(int pa filterCondition.recruitKeyword(), educationLevel, filterCondition.careerYear(), recruitSortType, pageRequest); - return createPageResponseDTO(page, size, findRecruitPage, member); + return createPageResponseDTO(findRecruitPage, member); } public RecruitInfoDTO findRecruitInfo(Member member, Long recruitId) { @@ -266,22 +266,19 @@ private boolean isEmptyContentBuilder(StringBuilder contentBuilder, int projectE == PROJECT_PREFIX.length() + projectEnterCnt + INTERN_PREFIX.length() + internEnterCnt; } - private PageResponseDTO> createPageResponseDTO(int page, - int size, Page findRecruitPage, Member member) { + private PageResponseDTO createPageResponseDTO(Page findRecruitPage, Member member) { Set scrapedRecruitIds = recruitScrapRepository.findRecruitIdsByMember(member); - boolean hasNext = findRecruitPage.getSize() == size + 1; + RecommendRecruitsDTO recommendRecruitsDTO = RecruitConverter.toRecommendRecruitsDTO(member, + findRecruitPage.stream() + .map(recruit -> RecruitConverter.toRecruitThumbNailInfoDTO(recruit, + scrapedRecruitIds.contains(recruit.getId()))) + .toList()); - List recommendRecruitDTOList = findRecruitPage.stream() - .limit(size) - .map(recruit -> RecruitConverter.toRecommendRecruitDTO(recruit, - scrapedRecruitIds.contains(recruit.getId()))) - .toList(); - - return PageResponseDTO.>builder() - .page(page) - .hasNext(hasNext) - .result(recommendRecruitDTOList) + return PageResponseDTO.builder() + .page(findRecruitPage.getNumber() + 1) + .totalPages(findRecruitPage.getTotalPages()) + .result(recommendRecruitsDTO) .build(); } } diff --git a/src/main/java/UMC/career_mate/global/common/PageResponseDTO.java b/src/main/java/UMC/career_mate/global/common/PageResponseDTO.java index a4cd84b..bfdd2e6 100644 --- a/src/main/java/UMC/career_mate/global/common/PageResponseDTO.java +++ b/src/main/java/UMC/career_mate/global/common/PageResponseDTO.java @@ -1,12 +1,15 @@ package UMC.career_mate.global.common; +import com.fasterxml.jackson.annotation.JsonInclude; import lombok.Builder; @Builder +@JsonInclude(JsonInclude.Include.NON_NULL) public record PageResponseDTO( int page, - boolean hasNext, + Boolean hasNext, + Integer totalPages, T result ) {