diff --git a/src/main/java/umc/kkijuk/server/dashboard/service/DashBoardServiceImpl.java b/src/main/java/umc/kkijuk/server/dashboard/service/DashBoardServiceImpl.java index ab3bcb85..539fff8b 100644 --- a/src/main/java/umc/kkijuk/server/dashboard/service/DashBoardServiceImpl.java +++ b/src/main/java/umc/kkijuk/server/dashboard/service/DashBoardServiceImpl.java @@ -11,7 +11,7 @@ import umc.kkijuk.server.dashboard.controller.response.IntroduceRemindResponse; import umc.kkijuk.server.dashboard.controller.response.RecruitRemindResponse; import umc.kkijuk.server.introduce.domain.Introduce; -import umc.kkijuk.server.introduce.domain.IntroduceRepository; +import umc.kkijuk.server.introduce.repository.IntroduceRepository; import umc.kkijuk.server.member.domain.Member; import umc.kkijuk.server.recruit.controller.port.RecruitService; import umc.kkijuk.server.recruit.domain.Recruit; diff --git a/src/main/java/umc/kkijuk/server/introduce/controller/IntroduceController.java b/src/main/java/umc/kkijuk/server/introduce/controller/IntroduceController.java index d80c70fa..8e945b75 100644 --- a/src/main/java/umc/kkijuk/server/introduce/controller/IntroduceController.java +++ b/src/main/java/umc/kkijuk/server/introduce/controller/IntroduceController.java @@ -11,14 +11,18 @@ import umc.kkijuk.server.introduce.common.BaseResponse; import umc.kkijuk.server.introduce.controller.response.IntroduceListResponse; import umc.kkijuk.server.introduce.controller.response.IntroduceResponse; +import umc.kkijuk.server.introduce.controller.response.MasterIntroduceResponse; import umc.kkijuk.server.introduce.dto.*; import umc.kkijuk.server.introduce.service.IntroduceService; +import umc.kkijuk.server.introduce.service.MasterIntroduceService; import umc.kkijuk.server.login.argumentresolver.Login; import umc.kkijuk.server.login.controller.dto.LoginInfo; import umc.kkijuk.server.member.domain.Member; import umc.kkijuk.server.member.service.MemberService; +import java.util.ArrayList; import java.util.List; +import java.util.Map; @Tag(name = "introduce", description = "자기소개서 API") @RestController @@ -26,6 +30,7 @@ @RequestMapping("/history/intro/") public class IntroduceController { private final IntroduceService introduceService; + private final MasterIntroduceService masterIntroduceService; private final MemberService memberService; private final Member requestMember = Member.builder() @@ -90,4 +95,14 @@ public ResponseEntity delete( .body(new BaseResponse<>(HttpStatus.OK.value(), "자기소개서 삭제 완료", intro_Id)); } + @GetMapping("/search") + @Operation(summary = "키워드로 자기소개서 문단 검색") + public ResponseEntity> searchIntroduceByKeyword(@Login LoginInfo loginInfo, @RequestParam String keyword) { + Member requestMember = memberService.getById(loginInfo.getMemberId()); + Map response = introduceService.searchIntroduceAndMasterByKeyword(keyword, requestMember); + return ResponseEntity.status(HttpStatus.OK).body(response); + } + + + } diff --git a/src/main/java/umc/kkijuk/server/introduce/controller/response/FindIntroduceResponse.java b/src/main/java/umc/kkijuk/server/introduce/controller/response/FindIntroduceResponse.java new file mode 100644 index 00000000..366977c3 --- /dev/null +++ b/src/main/java/umc/kkijuk/server/introduce/controller/response/FindIntroduceResponse.java @@ -0,0 +1,17 @@ +package umc.kkijuk.server.introduce.controller.response; + +import lombok.*; + +import java.time.LocalDate; +import java.time.LocalDateTime; + +@Data +@Getter +@Builder +@AllArgsConstructor +public class FindIntroduceResponse { + private Long introId; + private String title; + private String content; + private LocalDate createdDate; +} diff --git a/src/main/java/umc/kkijuk/server/introduce/controller/response/FindMasterIntroduceResponse.java b/src/main/java/umc/kkijuk/server/introduce/controller/response/FindMasterIntroduceResponse.java new file mode 100644 index 00000000..437b32dd --- /dev/null +++ b/src/main/java/umc/kkijuk/server/introduce/controller/response/FindMasterIntroduceResponse.java @@ -0,0 +1,17 @@ +package umc.kkijuk.server.introduce.controller.response; + +import lombok.*; + +import java.time.LocalDate; +import java.time.LocalDateTime; + +@Data +@Getter +@Builder +@AllArgsConstructor +public class FindMasterIntroduceResponse { + private Long masterIntroId; + private String title; + private String content; + private LocalDate createdDate; +} diff --git a/src/main/java/umc/kkijuk/server/introduce/domain/MasterIntroduceRepository.java b/src/main/java/umc/kkijuk/server/introduce/domain/MasterIntroduceRepository.java deleted file mode 100644 index 5d05c2ba..00000000 --- a/src/main/java/umc/kkijuk/server/introduce/domain/MasterIntroduceRepository.java +++ /dev/null @@ -1,11 +0,0 @@ -package umc.kkijuk.server.introduce.domain; - -import org.springframework.data.jpa.repository.JpaRepository; -import umc.kkijuk.server.introduce.dto.QuestionDto; - -import java.util.List; -import java.util.Optional; - -public interface MasterIntroduceRepository extends JpaRepository { - Optional findByMemberId(Long memberId); -} diff --git a/src/main/java/umc/kkijuk/server/introduce/domain/IntroduceRepository.java b/src/main/java/umc/kkijuk/server/introduce/repository/IntroduceRepository.java similarity index 69% rename from src/main/java/umc/kkijuk/server/introduce/domain/IntroduceRepository.java rename to src/main/java/umc/kkijuk/server/introduce/repository/IntroduceRepository.java index 1bf324ae..e7ff9a75 100644 --- a/src/main/java/umc/kkijuk/server/introduce/domain/IntroduceRepository.java +++ b/src/main/java/umc/kkijuk/server/introduce/repository/IntroduceRepository.java @@ -1,4 +1,4 @@ -package umc.kkijuk.server.introduce.domain; +package umc.kkijuk.server.introduce.repository; import org.springframework.data.domain.Page; import org.springframework.data.jpa.repository.JpaRepository; @@ -6,6 +6,8 @@ import org.springframework.data.repository.query.Param; import org.springframework.data.domain.Pageable; +import umc.kkijuk.server.introduce.domain.Introduce; + import java.util.List; import java.util.Optional; @@ -16,4 +18,10 @@ public interface IntroduceRepository extends JpaRepository { @Query("SELECT i FROM Introduce i WHERE i.memberId = :memberId AND i.state = :state ORDER BY i.recruit.endTime ASC") Page findByMemberIdAndStateOrderByEndTimeAsc(@Param("memberId") Long memberId, @Param("state") int state, Pageable pageable); + @Query("SELECT i FROM Introduce i " + + "JOIN i.questions q " + + "WHERE i.memberId = :memberId AND q.content LIKE %:keyword%") + List searchIntroduceByKeywordForMember(String keyword, Long memberId); + + } diff --git a/src/main/java/umc/kkijuk/server/introduce/repository/MasterIntroduceRepository.java b/src/main/java/umc/kkijuk/server/introduce/repository/MasterIntroduceRepository.java new file mode 100644 index 00000000..31eff56a --- /dev/null +++ b/src/main/java/umc/kkijuk/server/introduce/repository/MasterIntroduceRepository.java @@ -0,0 +1,18 @@ +package umc.kkijuk.server.introduce.repository; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; +import umc.kkijuk.server.introduce.domain.MasterIntroduce; + +import java.util.List; +import java.util.Optional; + +public interface MasterIntroduceRepository extends JpaRepository { + Optional findByMemberId(Long memberId); + @Query("SELECT m FROM MasterIntroduce m " + + "JOIN m.masterQuestion mq " + + "WHERE m.memberId = :memberId AND mq.content LIKE %:keyword%") + List searchMasterIntroduceByKeywordForMember(String keyword, Long memberId); + +} diff --git a/src/main/java/umc/kkijuk/server/introduce/domain/MasterQuestionRepository.java b/src/main/java/umc/kkijuk/server/introduce/repository/MasterQuestionRepository.java similarity index 57% rename from src/main/java/umc/kkijuk/server/introduce/domain/MasterQuestionRepository.java rename to src/main/java/umc/kkijuk/server/introduce/repository/MasterQuestionRepository.java index bf3eeca5..880fa0f5 100644 --- a/src/main/java/umc/kkijuk/server/introduce/domain/MasterQuestionRepository.java +++ b/src/main/java/umc/kkijuk/server/introduce/repository/MasterQuestionRepository.java @@ -1,6 +1,7 @@ -package umc.kkijuk.server.introduce.domain; +package umc.kkijuk.server.introduce.repository; import org.springframework.data.jpa.repository.JpaRepository; +import umc.kkijuk.server.introduce.domain.MasterQuestion; public interface MasterQuestionRepository extends JpaRepository { } diff --git a/src/main/java/umc/kkijuk/server/introduce/domain/QuestionRepository.java b/src/main/java/umc/kkijuk/server/introduce/repository/QuestionRepository.java similarity index 65% rename from src/main/java/umc/kkijuk/server/introduce/domain/QuestionRepository.java rename to src/main/java/umc/kkijuk/server/introduce/repository/QuestionRepository.java index a25e7a4a..de86d77f 100644 --- a/src/main/java/umc/kkijuk/server/introduce/domain/QuestionRepository.java +++ b/src/main/java/umc/kkijuk/server/introduce/repository/QuestionRepository.java @@ -1,6 +1,7 @@ -package umc.kkijuk.server.introduce.domain; +package umc.kkijuk.server.introduce.repository; import org.springframework.data.jpa.repository.JpaRepository; +import umc.kkijuk.server.introduce.domain.Question; import java.util.List; import java.util.Optional; diff --git a/src/main/java/umc/kkijuk/server/introduce/service/IntroduceService.java b/src/main/java/umc/kkijuk/server/introduce/service/IntroduceService.java index b862b0fd..ac44cb57 100644 --- a/src/main/java/umc/kkijuk/server/introduce/service/IntroduceService.java +++ b/src/main/java/umc/kkijuk/server/introduce/service/IntroduceService.java @@ -1,172 +1,18 @@ package umc.kkijuk.server.introduce.service; -import jakarta.transaction.Transactional; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import umc.kkijuk.server.common.domian.exception.IntroFoundException; -import umc.kkijuk.server.common.domian.exception.IntroOwnerMismatchException; -import umc.kkijuk.server.common.domian.exception.RecruitOwnerMismatchException; -import umc.kkijuk.server.common.domian.exception.ResourceNotFoundException; -import umc.kkijuk.server.introduce.controller.response.IntroduceListResponse; -import umc.kkijuk.server.introduce.controller.response.IntroduceResponse; -import umc.kkijuk.server.introduce.domain.*; -import umc.kkijuk.server.introduce.dto.*; +import umc.kkijuk.server.introduce.controller.response.*; +import umc.kkijuk.server.introduce.dto.IntroduceReqDto; import umc.kkijuk.server.member.domain.Member; -import umc.kkijuk.server.recruit.infrastructure.RecruitEntity; -import umc.kkijuk.server.recruit.infrastructure.RecruitJpaRepository; -import java.time.LocalDateTime; -import java.util.*; -import java.util.stream.Collectors; +import java.util.List; +import java.util.Map; -@RequiredArgsConstructor -@Service -public class IntroduceService { +public interface IntroduceService { - private final IntroduceRepository introduceRepository; - private final RecruitJpaRepository recruitJpaRepository; - private final QuestionRepository questionRepository; - - @Transactional - public IntroduceResponse saveIntro(Member requestMember, Long recruitId, IntroduceReqDto introduceReqDto){ - RecruitEntity recruit=recruitJpaRepository.findById(recruitId) - .orElseThrow(()-> new ResourceNotFoundException("recruit ", recruitId)); - if (introduceRepository.findByRecruitId(recruitId).isPresent()) { - throw new IntroFoundException("이미 자기소개서가 존재합니다"); - } - - List questions = introduceReqDto.getQuestionList().stream() - .map(dto -> new Question(dto.getTitle(), dto.getContent(), dto.getNumber())) - .collect(Collectors.toList()); - - Introduce introduce=Introduce.builder() - .memberId(requestMember.getId()) - .recruit(recruit) - .questions(questions) - .state(introduceReqDto.getState()) - .build(); - - introduceRepository.save(introduce); - /*List introduceList=getIntroduceTitles();*/ - return new IntroduceResponse(introduce, introduceReqDto.getQuestionList()/*,introduceList*/); - } - - @Transactional - public IntroduceResponse getIntro(Member requestMember, Long introId){ - Introduce introduce=introduceRepository.findById(introId) - .orElseThrow(()-> new ResourceNotFoundException("introduce ", introId)); - if (!introduce.getMemberId().equals(requestMember.getId())) { - throw new IntroOwnerMismatchException(); - } - - List questionList = introduce.getQuestions() - .stream() - .map(question -> new QuestionDto(question.getTitle(), question.getContent(), question.getNumber())) - .collect(Collectors.toList()); - - /*List introduceList=getIntroduceTitles();*/ - - return new IntroduceResponse(introduce, questionList/*, introduceList*/); - } - - @Transactional - public List getIntroList(Member requestMember){ - List introduces = introduceRepository.findAllByMemberId(requestMember.getId()) - .orElseThrow(IntroOwnerMismatchException::new); - - return introduces.stream() - .map(IntroduceListResponse::new) - .collect(Collectors.toList()); - } - - @Transactional - public IntroduceResponse updateIntro(Member requestMember, Long introId, IntroduceReqDto introduceReqDto) throws Exception{ - Introduce introduce=introduceRepository.findById(introId) - .orElseThrow(()-> new ResourceNotFoundException("introduce ", introId)); - - if (!introduce.getMemberId().equals(requestMember.getId())) { - throw new IntroOwnerMismatchException(); - } - - introduce.update(introduceReqDto.getState()); - - List existingQuestions = introduce.getQuestions(); - Map existingQuestionsMap = existingQuestions.stream() - .collect(Collectors.toMap(Question::getNumber, q -> q)); - - List questionDtos = introduceReqDto.getQuestionList(); - List updatedQuestions = new ArrayList<>(); - - for (QuestionDto questionDto : questionDtos) { - Integer number = questionDto.getNumber(); - Question existingQuestion = existingQuestionsMap.get(number); - - if (existingQuestion != null) { - existingQuestion.update(questionDto.getTitle(), questionDto.getContent()); - updatedQuestions.add(existingQuestion); - } else { - Question newQuestion = new Question(); - newQuestion.setTitle(questionDto.getTitle()); - newQuestion.setContent(questionDto.getContent()); - newQuestion.setNumber(questionDto.getNumber()); - newQuestion.setIntroduce(introduce); - updatedQuestions.add(newQuestion); - } - } - - List toRemove = existingQuestions.stream() - .filter(q -> !questionDtos.stream() - .anyMatch(dto -> dto.getNumber() == q.getNumber())) - .collect(Collectors.toList()); - - toRemove.forEach(question -> { - introduce.getQuestions().remove(question); - questionRepository.delete(question); - }); - - introduce.getQuestions().clear(); - introduce.getQuestions().addAll(updatedQuestions); - - introduceRepository.save(introduce); - - List responseQuestionList = introduce.getQuestions().stream() - .map(question -> QuestionDto.builder() - .title(question.getTitle()) - .content(question.getContent()) - .number(question.getNumber()) - .build()) - .collect(Collectors.toList()); - - return IntroduceResponse.builder() - .introduce(introduce) - .questionList(responseQuestionList) - .build(); - } - - - @Transactional - public Long deleteIntro(Member requestMember, Long introId){ - Introduce introduce=introduceRepository.findById(introId) - .orElseThrow(()-> new ResourceNotFoundException("introduce ", introId)); - if (!introduce.getMemberId().equals(requestMember.getId())) { - throw new IntroOwnerMismatchException(); - } - - introduceRepository.delete(introduce); - - return introduce.getId(); - } - - /* @Transactional - public List getIntroduceTitles() { - // Fetch all Introduce entities - List introduces = introduceRepository.findAll(); - - // Map Introduce entities to Recruit titles - return introduces.stream() - .map(introduce -> recruitJpaRepository.findById(introduce.getRecruit().toModel().getId())) // Get the Recruit entity - .filter(Optional::isPresent) // Filter out any empty results - .map(opt -> opt.get().toModel().getTitle()) // Get the title of the Recruit - .collect(Collectors.toList()); // Collect titles into a List - }*/ + IntroduceResponse saveIntro(Member requestMember, Long recruitId, IntroduceReqDto introduceReqDto); + IntroduceResponse getIntro(Member requestMember, Long introId); + List getIntroList(Member requestMember); + IntroduceResponse updateIntro(Member requestMember, Long introId, IntroduceReqDto introduceReqDto) throws Exception; + Long deleteIntro(Member requestMember, Long introId); + Map searchIntroduceAndMasterByKeyword(String keyword, Member requestMember); } diff --git a/src/main/java/umc/kkijuk/server/introduce/service/IntroduceServiceImpl.java b/src/main/java/umc/kkijuk/server/introduce/service/IntroduceServiceImpl.java new file mode 100644 index 00000000..ec6dc8b3 --- /dev/null +++ b/src/main/java/umc/kkijuk/server/introduce/service/IntroduceServiceImpl.java @@ -0,0 +1,201 @@ +package umc.kkijuk.server.introduce.service; + +import jakarta.transaction.Transactional; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import umc.kkijuk.server.common.domian.exception.IntroFoundException; +import umc.kkijuk.server.common.domian.exception.IntroOwnerMismatchException; +import umc.kkijuk.server.common.domian.exception.ResourceNotFoundException; +import umc.kkijuk.server.introduce.controller.response.*; +import umc.kkijuk.server.introduce.domain.*; +import umc.kkijuk.server.introduce.dto.IntroduceReqDto; +import umc.kkijuk.server.introduce.dto.QuestionDto; +import umc.kkijuk.server.introduce.repository.IntroduceRepository; +import umc.kkijuk.server.introduce.repository.MasterIntroduceRepository; +import umc.kkijuk.server.introduce.repository.QuestionRepository; +import umc.kkijuk.server.member.domain.Member; +import umc.kkijuk.server.recruit.infrastructure.RecruitEntity; +import umc.kkijuk.server.recruit.infrastructure.RecruitJpaRepository; + +import java.util.*; +import java.util.stream.Collectors; + +@RequiredArgsConstructor +@Service +public class IntroduceServiceImpl implements IntroduceService { + + private final IntroduceRepository introduceRepository; + private final RecruitJpaRepository recruitJpaRepository; + private final QuestionRepository questionRepository; + private final MasterIntroduceRepository masterIntroduceRepository; + + @Override + @Transactional + public IntroduceResponse saveIntro(Member requestMember, Long recruitId, IntroduceReqDto introduceReqDto) { + RecruitEntity recruit = recruitJpaRepository.findById(recruitId) + .orElseThrow(() -> new ResourceNotFoundException("recruit ", recruitId)); + if (introduceRepository.findByRecruitId(recruitId).isPresent()) { + throw new IntroFoundException("이미 자기소개서가 존재합니다"); + } + + List questions = introduceReqDto.getQuestionList().stream() + .map(dto -> new Question(dto.getTitle(), dto.getContent(), dto.getNumber())) + .collect(Collectors.toList()); + + Introduce introduce = Introduce.builder() + .memberId(requestMember.getId()) + .recruit(recruit) + .questions(questions) + .state(introduceReqDto.getState()) + .build(); + + introduceRepository.save(introduce); + return new IntroduceResponse(introduce, introduceReqDto.getQuestionList()); + } + + @Override + @Transactional + public IntroduceResponse getIntro(Member requestMember, Long introId) { + Introduce introduce = introduceRepository.findById(introId) + .orElseThrow(() -> new ResourceNotFoundException("introduce ", introId)); + if (!introduce.getMemberId().equals(requestMember.getId())) { + throw new IntroOwnerMismatchException(); + } + + List questionList = introduce.getQuestions() + .stream() + .map(question -> new QuestionDto(question.getTitle(), question.getContent(), question.getNumber())) + .collect(Collectors.toList()); + + return new IntroduceResponse(introduce, questionList); + } + + @Override + @Transactional + public List getIntroList(Member requestMember) { + List introduces = introduceRepository.findAllByMemberId(requestMember.getId()) + .orElseThrow(IntroOwnerMismatchException::new); + + return introduces.stream() + .map(IntroduceListResponse::new) + .collect(Collectors.toList()); + } + + @Override + @Transactional + public IntroduceResponse updateIntro(Member requestMember, Long introId, IntroduceReqDto introduceReqDto) throws Exception { + Introduce introduce = introduceRepository.findById(introId) + .orElseThrow(() -> new ResourceNotFoundException("introduce ", introId)); + + if (!introduce.getMemberId().equals(requestMember.getId())) { + throw new IntroOwnerMismatchException(); + } + + introduce.update(introduceReqDto.getState()); + + List existingQuestions = introduce.getQuestions(); + Map existingQuestionsMap = existingQuestions.stream() + .collect(Collectors.toMap(Question::getNumber, q -> q)); + + List questionDtos = introduceReqDto.getQuestionList(); + List updatedQuestions = new ArrayList<>(); + + for (QuestionDto questionDto : questionDtos) { + Integer number = questionDto.getNumber(); + Question existingQuestion = existingQuestionsMap.get(number); + + if (existingQuestion != null) { + existingQuestion.update(questionDto.getTitle(), questionDto.getContent()); + updatedQuestions.add(existingQuestion); + } else { + Question newQuestion = new Question(); + newQuestion.setTitle(questionDto.getTitle()); + newQuestion.setContent(questionDto.getContent()); + newQuestion.setNumber(questionDto.getNumber()); + newQuestion.setIntroduce(introduce); + updatedQuestions.add(newQuestion); + } + } + + List toRemove = existingQuestions.stream() + .filter(q -> !questionDtos.stream() + .anyMatch(dto -> dto.getNumber() == q.getNumber())) + .collect(Collectors.toList()); + + toRemove.forEach(question -> { + introduce.getQuestions().remove(question); + questionRepository.delete(question); + }); + + introduce.getQuestions().clear(); + introduce.getQuestions().addAll(updatedQuestions); + + introduceRepository.save(introduce); + + List responseQuestionList = introduce.getQuestions().stream() + .map(question -> QuestionDto.builder() + .title(question.getTitle()) + .content(question.getContent()) + .number(question.getNumber()) + .build()) + .collect(Collectors.toList()); + + return IntroduceResponse.builder() + .introduce(introduce) + .questionList(responseQuestionList) + .build(); + } + + @Override + @Transactional + public Long deleteIntro(Member requestMember, Long introId) { + Introduce introduce = introduceRepository.findById(introId) + .orElseThrow(() -> new ResourceNotFoundException("introduce ", introId)); + if (!introduce.getMemberId().equals(requestMember.getId())) { + throw new IntroOwnerMismatchException(); + } + + introduceRepository.delete(introduce); + + return introduce.getId(); + } + + @Override + public Map searchIntroduceAndMasterByKeyword(String keyword, Member requestMember) { + List introduceList = introduceRepository.searchIntroduceByKeywordForMember(keyword, requestMember.getId()) + .stream() + .flatMap(introduce -> introduce.getQuestions().stream() + .filter(q -> q.getContent().contains(keyword)) + .map(q -> FindIntroduceResponse.builder() + .introId(introduce.getId()) + .title(introduce.getRecruit().getTitle()) + .content(q.getContent()) + .createdDate(introduce.getCreatedAt().toLocalDate()) + .build())) + .collect(Collectors.toList()); + + List masterIntroduceList = masterIntroduceRepository.searchMasterIntroduceByKeywordForMember(keyword, requestMember.getId()) + .stream() + .flatMap(masterIntroduce -> masterIntroduce.getMasterQuestion().stream() + .filter(mq -> mq.getContent().contains(keyword)) + .map(mq -> FindMasterIntroduceResponse.builder() + .masterIntroId(masterIntroduce.getId()) + .title("Master") + .content(mq.getContent()) + .createdDate(masterIntroduce.getCreatedAt().toLocalDate()) + .build())) + .collect(Collectors.toList()); + + List result = new ArrayList<>(); + result.addAll(masterIntroduceList); + result.addAll(introduceList); + + int count = result.size(); + + Map response = new LinkedHashMap<>(); + response.put("count", count); + response.put("data", result); + + return response; + } +} diff --git a/src/main/java/umc/kkijuk/server/introduce/service/MasterIntroduceService.java b/src/main/java/umc/kkijuk/server/introduce/service/MasterIntroduceService.java index 5acae91b..d637ddac 100644 --- a/src/main/java/umc/kkijuk/server/introduce/service/MasterIntroduceService.java +++ b/src/main/java/umc/kkijuk/server/introduce/service/MasterIntroduceService.java @@ -1,127 +1,11 @@ package umc.kkijuk.server.introduce.service; -import jakarta.transaction.Transactional; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import umc.kkijuk.server.common.domian.exception.IntroFoundException; -import umc.kkijuk.server.common.domian.exception.IntroOwnerMismatchException; -import umc.kkijuk.server.common.domian.exception.ResourceNotFoundException; import umc.kkijuk.server.introduce.controller.response.MasterIntroduceResponse; -import umc.kkijuk.server.introduce.domain.*; import umc.kkijuk.server.introduce.dto.IntroduceReqDto; -import umc.kkijuk.server.introduce.dto.QuestionDto; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -@RequiredArgsConstructor -@Service -public class MasterIntroduceService{ - private final MasterIntroduceRepository masterIntroduceRepository; - private final MasterQuestionRepository masterQuestionRepository; - - @Transactional - public MasterIntroduceResponse saveMasterIntro(Long memberId, IntroduceReqDto introduceReqDto){ - if (masterIntroduceRepository.findByMemberId(memberId).isPresent()) { - throw new IntroFoundException("이미 자기소개서가 존재합니다"); - } - - List masterQuestions = introduceReqDto.getQuestionList().stream() - .map(dto -> new MasterQuestion(dto.getTitle(), dto.getContent(), dto.getNumber())) - .collect(Collectors.toList()); - - MasterIntroduce masterIntroduce = MasterIntroduce.builder() - .memberId(memberId) - .masterQuestion(masterQuestions) - .state(introduceReqDto.getState()) - .build(); - - masterIntroduceRepository.save(masterIntroduce); - - return new MasterIntroduceResponse(masterIntroduce, introduceReqDto.getQuestionList()); - } - - @Transactional - public MasterIntroduceResponse getMasterIntro(Long memberId){ - MasterIntroduce masterIntroduce = masterIntroduceRepository.findByMemberId(memberId) - .orElseThrow(() -> new ResourceNotFoundException("MasterIntroduce", memberId)); - if (!masterIntroduce.getMemberId().equals(memberId)) { - throw new IntroOwnerMismatchException(); - } - List masterQuestionList = masterIntroduce.getMasterQuestion() - .stream() - .map(question -> new QuestionDto(question.getTitle(), question.getContent(), question.getNumber())) - .collect(Collectors.toList()); - return new MasterIntroduceResponse(masterIntroduce, masterQuestionList); - } - - @Transactional - public MasterIntroduceResponse updateMasterIntro(Long memberId, IntroduceReqDto introduceReqDto) throws Exception { - MasterIntroduce masterIntroduce = masterIntroduceRepository.findByMemberId(memberId) - .orElseThrow(() -> new ResourceNotFoundException("masterIntroduce", memberId)); - - if (!masterIntroduce.getMemberId().equals(memberId)) { - throw new IntroOwnerMismatchException(); - } - - // 상태 업데이트 - masterIntroduce.update(introduceReqDto.getState()); - - List existingQuestions = masterIntroduce.getMasterQuestion(); - Map existingQuestionsMap = existingQuestions.stream() - .collect(Collectors.toMap(MasterQuestion::getNumber, q -> q)); - - List questionDtos = introduceReqDto.getQuestionList(); - List updatedQuestions = new ArrayList<>(); - - for (QuestionDto questionDto : questionDtos) { - Integer number = questionDto.getNumber(); - MasterQuestion existingQuestion = existingQuestionsMap.get(number); - - if (existingQuestion != null) { - existingQuestion.update(questionDto.getTitle(), questionDto.getContent()); - updatedQuestions.add(existingQuestion); - } else { - MasterQuestion newQuestion = new MasterQuestion(); - newQuestion.setTitle(questionDto.getTitle()); - newQuestion.setContent(questionDto.getContent()); - newQuestion.setNumber(questionDto.getNumber()); - newQuestion.setMasterIntroduce(masterIntroduce); - updatedQuestions.add(newQuestion); - } - } - - List toRemove = existingQuestions.stream() - .filter(q -> questionDtos.stream().noneMatch(dto -> dto.getNumber() == q.getNumber())) - .collect(Collectors.toList()); - - for (MasterQuestion question : toRemove) { - masterIntroduce.getMasterQuestion().remove(question); - masterQuestionRepository.delete(question); - } - - // 기존 질문 리스트에 업데이트된 질문들 추가 - masterIntroduce.getMasterQuestion().clear(); - masterIntroduce.getMasterQuestion().addAll(updatedQuestions); - - // masterIntroduce 저장 - masterIntroduce = masterIntroduceRepository.save(masterIntroduce); - - // 응답용 DTO 생성 - List responseQuestionList = updatedQuestions.stream() - .map(question -> QuestionDto.builder() - .title(question.getTitle()) - .content(question.getContent()) - .number(question.getNumber()) - .build()) - .collect(Collectors.toList()); - - return MasterIntroduceResponse.builder() - .masterIntroduce(masterIntroduce) - .questionList(responseQuestionList) - .build(); - } +public interface MasterIntroduceService { + MasterIntroduceResponse saveMasterIntro(Long memberId, IntroduceReqDto introduceReqDto); + MasterIntroduceResponse getMasterIntro(Long memberId); + MasterIntroduceResponse updateMasterIntro(Long memberId, IntroduceReqDto introduceReqDto) throws Exception; } diff --git a/src/main/java/umc/kkijuk/server/introduce/service/MasterIntroduceServiceImpl.java b/src/main/java/umc/kkijuk/server/introduce/service/MasterIntroduceServiceImpl.java new file mode 100644 index 00000000..8c69f84c --- /dev/null +++ b/src/main/java/umc/kkijuk/server/introduce/service/MasterIntroduceServiceImpl.java @@ -0,0 +1,131 @@ +package umc.kkijuk.server.introduce.service; + +import jakarta.transaction.Transactional; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import umc.kkijuk.server.common.domian.exception.IntroFoundException; +import umc.kkijuk.server.common.domian.exception.IntroOwnerMismatchException; +import umc.kkijuk.server.common.domian.exception.ResourceNotFoundException; +import umc.kkijuk.server.introduce.controller.response.MasterIntroduceResponse; +import umc.kkijuk.server.introduce.domain.MasterIntroduce; +import umc.kkijuk.server.introduce.domain.MasterQuestion; +import umc.kkijuk.server.introduce.dto.IntroduceReqDto; +import umc.kkijuk.server.introduce.dto.QuestionDto; +import umc.kkijuk.server.introduce.repository.MasterIntroduceRepository; +import umc.kkijuk.server.introduce.repository.MasterQuestionRepository; + +import java.util.*; +import java.util.stream.Collectors; + +@RequiredArgsConstructor +@Service +public class MasterIntroduceServiceImpl implements MasterIntroduceService { + + private final MasterIntroduceRepository masterIntroduceRepository; + private final MasterQuestionRepository masterQuestionRepository; + + @Override + @Transactional + public MasterIntroduceResponse saveMasterIntro(Long memberId, IntroduceReqDto introduceReqDto) { + if (masterIntroduceRepository.findByMemberId(memberId).isPresent()) { + throw new IntroFoundException("이미 자기소개서가 존재합니다"); + } + + List masterQuestions = introduceReqDto.getQuestionList().stream() + .map(dto -> new MasterQuestion(dto.getTitle(), dto.getContent(), dto.getNumber())) + .collect(Collectors.toList()); + + MasterIntroduce masterIntroduce = MasterIntroduce.builder() + .memberId(memberId) + .masterQuestion(masterQuestions) + .state(introduceReqDto.getState()) + .build(); + + masterIntroduceRepository.save(masterIntroduce); + + return new MasterIntroduceResponse(masterIntroduce, introduceReqDto.getQuestionList()); + } + + @Override + @Transactional + public MasterIntroduceResponse getMasterIntro(Long memberId) { + MasterIntroduce masterIntroduce = masterIntroduceRepository.findByMemberId(memberId) + .orElseThrow(() -> new ResourceNotFoundException("MasterIntroduce", memberId)); + if (!masterIntroduce.getMemberId().equals(memberId)) { + throw new IntroOwnerMismatchException(); + } + List masterQuestionList = masterIntroduce.getMasterQuestion() + .stream() + .map(question -> new QuestionDto(question.getTitle(), question.getContent(), question.getNumber())) + .collect(Collectors.toList()); + return new MasterIntroduceResponse(masterIntroduce, masterQuestionList); + } + + @Override + @Transactional + public MasterIntroduceResponse updateMasterIntro(Long memberId, IntroduceReqDto introduceReqDto) throws Exception { + MasterIntroduce masterIntroduce = masterIntroduceRepository.findByMemberId(memberId) + .orElseThrow(() -> new ResourceNotFoundException("masterIntroduce", memberId)); + + if (!masterIntroduce.getMemberId().equals(memberId)) { + throw new IntroOwnerMismatchException(); + } + + // 상태 업데이트 + masterIntroduce.update(introduceReqDto.getState()); + + List existingQuestions = masterIntroduce.getMasterQuestion(); + Map existingQuestionsMap = existingQuestions.stream() + .collect(Collectors.toMap(MasterQuestion::getNumber, q -> q)); + + List questionDtos = introduceReqDto.getQuestionList(); + List updatedQuestions = new ArrayList<>(); + + for (QuestionDto questionDto : questionDtos) { + Integer number = questionDto.getNumber(); + MasterQuestion existingQuestion = existingQuestionsMap.get(number); + + if (existingQuestion != null) { + existingQuestion.update(questionDto.getTitle(), questionDto.getContent()); + updatedQuestions.add(existingQuestion); + } else { + MasterQuestion newQuestion = new MasterQuestion(); + newQuestion.setTitle(questionDto.getTitle()); + newQuestion.setContent(questionDto.getContent()); + newQuestion.setNumber(questionDto.getNumber()); + newQuestion.setMasterIntroduce(masterIntroduce); + updatedQuestions.add(newQuestion); + } + } + + List toRemove = existingQuestions.stream() + .filter(q -> questionDtos.stream().noneMatch(dto -> dto.getNumber() == q.getNumber())) + .collect(Collectors.toList()); + + for (MasterQuestion question : toRemove) { + masterIntroduce.getMasterQuestion().remove(question); + masterQuestionRepository.delete(question); + } + + // 기존 질문 리스트에 업데이트된 질문들 추가 + masterIntroduce.getMasterQuestion().clear(); + masterIntroduce.getMasterQuestion().addAll(updatedQuestions); + + // masterIntroduce 저장 + masterIntroduce = masterIntroduceRepository.save(masterIntroduce); + + // 응답용 DTO 생성 + List responseQuestionList = updatedQuestions.stream() + .map(question -> QuestionDto.builder() + .title(question.getTitle()) + .content(question.getContent()) + .number(question.getNumber()) + .build()) + .collect(Collectors.toList()); + + return MasterIntroduceResponse.builder() + .masterIntroduce(masterIntroduce) + .questionList(responseQuestionList) + .build(); + } +} diff --git a/src/main/java/umc/kkijuk/server/record/controller/response/AwardResponse.java b/src/main/java/umc/kkijuk/server/record/controller/response/AwardResponse.java index 86e70bb2..b93be289 100644 --- a/src/main/java/umc/kkijuk/server/record/controller/response/AwardResponse.java +++ b/src/main/java/umc/kkijuk/server/record/controller/response/AwardResponse.java @@ -13,14 +13,14 @@ @Getter @Builder public class AwardResponse { - private Long awardId; + private Long id; private String competitionName; private String administer; private String awardName; private YearMonth acquireDate; public AwardResponse(Award award) { - this.awardId = award.getId(); + this.id = award.getId(); this.competitionName = award.getCompetitionName(); this.administer = award.getAdminister(); this.awardName = award.getAwardName(); diff --git a/src/main/java/umc/kkijuk/server/record/controller/response/FileResponse.java b/src/main/java/umc/kkijuk/server/record/controller/response/FileResponse.java index 65755c9f..852581b0 100644 --- a/src/main/java/umc/kkijuk/server/record/controller/response/FileResponse.java +++ b/src/main/java/umc/kkijuk/server/record/controller/response/FileResponse.java @@ -12,7 +12,7 @@ @Builder @AllArgsConstructor public class FileResponse { - private Long fileId; + private Long id; private FileType fileType; private String fileTitle; private String keyName; @@ -20,7 +20,7 @@ public class FileResponse { private String url; public FileResponse(File file){ - this.fileId = file.getId(); + this.id = file.getId(); this.fileType = file.getFileType(); this.fileTitle = file.getFileTitle(); this.keyName = file.getKeyName(); diff --git a/src/main/java/umc/kkijuk/server/record/controller/response/LicenseResponse.java b/src/main/java/umc/kkijuk/server/record/controller/response/LicenseResponse.java index 74486adf..10b4e7bf 100644 --- a/src/main/java/umc/kkijuk/server/record/controller/response/LicenseResponse.java +++ b/src/main/java/umc/kkijuk/server/record/controller/response/LicenseResponse.java @@ -11,7 +11,7 @@ @Getter @Builder public class LicenseResponse { - private Long licenseId; + private Long id; private LicenseTag licenseTag; private String licenseName; private String administer; @@ -20,7 +20,7 @@ public class LicenseResponse { private YearMonth acquireDate; public LicenseResponse(License license) { - this.licenseId = license.getId(); + this.id = license.getId(); this.licenseTag = license.getLicenseTag(); this.licenseName = license.getLicenseName(); this.administer = license.getAdminister(); diff --git a/src/main/java/umc/kkijuk/server/record/controller/response/SkillResponse.java b/src/main/java/umc/kkijuk/server/record/controller/response/SkillResponse.java index c9a754a6..56ced700 100644 --- a/src/main/java/umc/kkijuk/server/record/controller/response/SkillResponse.java +++ b/src/main/java/umc/kkijuk/server/record/controller/response/SkillResponse.java @@ -13,13 +13,13 @@ @Getter @Builder public class SkillResponse { - private Long skillId; + private Long id; private SkillTag skillTag; private String skillName; private Workmanship workmanship; public SkillResponse(Skill skill) { - this.skillId = skill.getId(); + this.id = skill.getId(); this.skillTag = skill.getSkillTag(); this.skillName = skill.getSkillName(); this.workmanship = skill.getWorkmanship(); diff --git a/src/main/java/umc/kkijuk/server/recruit/infrastructure/RecruitEntity.java b/src/main/java/umc/kkijuk/server/recruit/infrastructure/RecruitEntity.java index 2322deba..1eed0411 100644 --- a/src/main/java/umc/kkijuk/server/recruit/infrastructure/RecruitEntity.java +++ b/src/main/java/umc/kkijuk/server/recruit/infrastructure/RecruitEntity.java @@ -1,6 +1,7 @@ package umc.kkijuk.server.recruit.infrastructure; import jakarta.persistence.*; +import lombok.Getter; import umc.kkijuk.server.common.converter.StringListToStringConverter; import umc.kkijuk.server.recruit.domain.Recruit; import umc.kkijuk.server.recruit.domain.RecruitStatus; @@ -10,6 +11,7 @@ import java.util.List; @Entity +@Getter @Table(name = "recruit") public class RecruitEntity { diff --git a/src/test/java/umc/kkijuk/server/introduce/controller/IntroduceControllerTest.java b/src/test/java/umc/kkijuk/server/introduce/controller/IntroduceControllerTest.java index feb9d109..0f72c23f 100644 --- a/src/test/java/umc/kkijuk/server/introduce/controller/IntroduceControllerTest.java +++ b/src/test/java/umc/kkijuk/server/introduce/controller/IntroduceControllerTest.java @@ -9,7 +9,6 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.web.server.LocalServerPort; import org.springframework.http.MediaType; import org.springframework.mock.web.MockHttpSession; import org.springframework.test.context.junit.jupiter.SpringExtension; @@ -19,6 +18,7 @@ import umc.kkijuk.server.introduce.domain.*; import umc.kkijuk.server.introduce.dto.IntroduceReqDto; import umc.kkijuk.server.introduce.dto.QuestionDto; +import umc.kkijuk.server.introduce.repository.IntroduceRepository; import umc.kkijuk.server.introduce.service.IntroduceService; import umc.kkijuk.server.login.controller.SessionConst; import umc.kkijuk.server.login.controller.dto.LoginInfo; @@ -34,7 +34,6 @@ import java.time.LocalDate; import java.time.LocalDateTime; -import java.time.YearMonth; import java.util.ArrayList; import java.util.Arrays; import java.util.List;