diff --git a/src/main/java/com/example/jehunonboarding/controller/JobPostingController.java b/src/main/java/com/example/jehunonboarding/controller/JobPostingController.java index c390ba0..b7ce71f 100644 --- a/src/main/java/com/example/jehunonboarding/controller/JobPostingController.java +++ b/src/main/java/com/example/jehunonboarding/controller/JobPostingController.java @@ -49,7 +49,8 @@ public ResponseEntity findDetail(@PathVariable int } @PostMapping("/v1/job-postings/{jobPostingId}/apply") - public ResponseEntity apply(@RequestBody JobPostingApplyRequest request) { + public ResponseEntity apply(@Valid @RequestBody JobPostingApplyRequest request) { + jobPostingService.apply(request.getCompanyId(), request.getMemberId()); return new ResponseEntity(new CommonResponse(true), HttpStatus.OK); } diff --git a/src/main/java/com/example/jehunonboarding/controller/request/JobPostingApplyRequest.java b/src/main/java/com/example/jehunonboarding/controller/request/JobPostingApplyRequest.java index 7557eff..0365e1b 100644 --- a/src/main/java/com/example/jehunonboarding/controller/request/JobPostingApplyRequest.java +++ b/src/main/java/com/example/jehunonboarding/controller/request/JobPostingApplyRequest.java @@ -1,9 +1,12 @@ package com.example.jehunonboarding.controller.request; +import jakarta.validation.constraints.NotNull; import lombok.Data; @Data public class JobPostingApplyRequest { + @NotNull(message = "companyId가 존재하지 않습니다") private int companyId; - private int userId; + @NotNull(message = "memberId가 존재하지 않습니다") + private int memberId; } diff --git a/src/main/java/com/example/jehunonboarding/domain/JobPostingService.java b/src/main/java/com/example/jehunonboarding/domain/JobPostingService.java index acd4215..eae0d36 100644 --- a/src/main/java/com/example/jehunonboarding/domain/JobPostingService.java +++ b/src/main/java/com/example/jehunonboarding/domain/JobPostingService.java @@ -2,6 +2,8 @@ import com.example.jehunonboarding.repository.CompanyRepository; import com.example.jehunonboarding.repository.JobPostingRepository; +import com.example.jehunonboarding.repository.ResumeRepository; +import com.example.jehunonboarding.repository.MemberRepository; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; @@ -14,6 +16,8 @@ public class JobPostingService { private final JobPostingRepository jobPostingRepository; private final CompanyRepository companyRepository; + private final MemberRepository memberRepository; + private final ResumeRepository resumeRepository; public void register(JobPostingRegisterInfo registerInfo) { companyRepository.findById(registerInfo.getCompanyId()) @@ -33,4 +37,19 @@ public void register(JobPostingRegisterInfo registerInfo) { public List search(Pageable pageable, String keyword) { return jobPostingRepository.findByKeyword(pageable, keyword); } + + public void apply(int companyId, int memberId) { + companyRepository.findById(companyId) + .orElseThrow(() -> new IllegalArgumentException("존재하지 않는 회사입니다.")); + + memberRepository.findById(memberId) + .orElseThrow(() -> new IllegalArgumentException("존재하지 않는 유저입니다.")); + + resumeRepository.findByMemberIdAndCompanyId(memberId, companyId) + .ifPresent(resume -> { + throw new IllegalArgumentException("이미 지원이 완료되었습니다."); + }); + + resumeRepository.save(new ResumeEntity(memberId, companyId)); + } } diff --git a/src/main/java/com/example/jehunonboarding/domain/MemberEntity.java b/src/main/java/com/example/jehunonboarding/domain/MemberEntity.java new file mode 100644 index 0000000..39b2fc2 --- /dev/null +++ b/src/main/java/com/example/jehunonboarding/domain/MemberEntity.java @@ -0,0 +1,20 @@ +package com.example.jehunonboarding.domain; + +import jakarta.persistence.*; +import lombok.NoArgsConstructor; + +@Entity +@Table(name = "member") +@NoArgsConstructor +public class MemberEntity { + @Id + @GeneratedValue + @Column(name = "id", nullable = false) + private Integer id; + + @Column(nullable = false) + private String name; + + @Column(nullable = false) + private String email; +} diff --git a/src/main/java/com/example/jehunonboarding/domain/ResumeEntity.java b/src/main/java/com/example/jehunonboarding/domain/ResumeEntity.java new file mode 100644 index 0000000..7d1798f --- /dev/null +++ b/src/main/java/com/example/jehunonboarding/domain/ResumeEntity.java @@ -0,0 +1,24 @@ +package com.example.jehunonboarding.domain; + +import jakarta.persistence.*; +import lombok.NoArgsConstructor; + +@Entity +@Table(name = "resume") +@NoArgsConstructor +public class ResumeEntity { + @Id + @GeneratedValue + private Long id; + + @Column(nullable = false) + private Long memberId; + + @Column(nullable = false) + private Long companyId; + + public ResumeEntity(int memberId, int companyId) { + this.memberId = (long) memberId; + this.companyId = (long) companyId; + } +} diff --git a/src/main/java/com/example/jehunonboarding/repository/MemberRepository.java b/src/main/java/com/example/jehunonboarding/repository/MemberRepository.java new file mode 100644 index 0000000..e9d4ebe --- /dev/null +++ b/src/main/java/com/example/jehunonboarding/repository/MemberRepository.java @@ -0,0 +1,7 @@ +package com.example.jehunonboarding.repository; + +import com.example.jehunonboarding.domain.MemberEntity; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface MemberRepository extends JpaRepository { +} diff --git a/src/main/java/com/example/jehunonboarding/repository/ResumeRepository.java b/src/main/java/com/example/jehunonboarding/repository/ResumeRepository.java new file mode 100644 index 0000000..3cb8532 --- /dev/null +++ b/src/main/java/com/example/jehunonboarding/repository/ResumeRepository.java @@ -0,0 +1,12 @@ +package com.example.jehunonboarding.repository; + +import com.example.jehunonboarding.domain.ResumeEntity; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.Optional; + +public interface ResumeRepository extends JpaRepository { + + Optional findByMemberIdAndCompanyId(int memberId, int companyId); + +} diff --git a/src/main/resources/data.sql b/src/main/resources/data.sql index 58cba22..50728b6 100644 --- a/src/main/resources/data.sql +++ b/src/main/resources/data.sql @@ -1 +1,3 @@ INSERT INTO company (id, company_name, nation, region) VALUES (1, '제훈테크', '한국', '서울'); + +INSERT INTO member (id, name, email) VALUES (1, '제훈제훈', 'test@test.com'); diff --git a/src/test/java/com/example/jehunonboarding/domain/JobPostingServiceTest.java b/src/test/java/com/example/jehunonboarding/domain/JobPostingServiceTest.java new file mode 100644 index 0000000..1aa3f49 --- /dev/null +++ b/src/test/java/com/example/jehunonboarding/domain/JobPostingServiceTest.java @@ -0,0 +1,86 @@ +package com.example.jehunonboarding.domain; + +import com.example.jehunonboarding.repository.CompanyRepository; +import com.example.jehunonboarding.repository.JobPostingRepository; +import com.example.jehunonboarding.repository.MemberRepository; +import com.example.jehunonboarding.repository.ResumeRepository; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.Optional; + +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +class JobPostingServiceTest { + + @InjectMocks + private JobPostingService jobPostingService; + + @Mock + private JobPostingRepository jobPostingRepository; + @Mock + private CompanyRepository companyRepository; + @Mock + private MemberRepository memberRepository; + @Mock + private ResumeRepository resumeRepository; + + @Test + @DisplayName("성공") + void testApply() { + // given + int companyId = 1; + int memberId = 1; + when(companyRepository.findById(companyId)).thenReturn(Optional.of(new Company())); + when(memberRepository.findById(companyId)).thenReturn(Optional.of(new MemberEntity())); + + // when + jobPostingService.apply(companyId, memberId); + + // then + verify(companyRepository, times(1)).findById(companyId); + } + + @Test + @DisplayName("회사가 조회되지 않으면 에러 발생") + void testApply_NotExistCompany() { + // given + int companyId = 1; + int memberId = 1; + + // when + assertThrows(IllegalArgumentException.class, () -> jobPostingService.apply(companyId, memberId)); + } + + @Test + @DisplayName("회원이 조회되지 않으면 에러 발생") + void testApply_NotExistMember() { + // given + int companyId = 1; + int memberId = 1; + when(companyRepository.findById(companyId)).thenReturn(Optional.of(new Company())); + + // when + assertThrows(IllegalArgumentException.class, () -> jobPostingService.apply(companyId, memberId)); + } + + @Test + @DisplayName("이미 지원된 이력서라면 에러 발생") + void testApply_AlreadyAppliedResume() { + // given + int companyId = 1; + int memberId = 1; + when(companyRepository.findById(companyId)).thenReturn(Optional.of(new Company())); + when(memberRepository.findById(companyId)).thenReturn(Optional.of(new MemberEntity())); + when(resumeRepository.findByMemberIdAndCompanyId(memberId, companyId)).thenReturn(Optional.of(new ResumeEntity())); + + // when + assertThrows(IllegalArgumentException.class, () -> jobPostingService.apply(companyId, memberId)); + } +} \ No newline at end of file