diff --git a/.idea/jpa-buddy.xml b/.idea/jpa-buddy.xml
new file mode 100644
index 0000000..966d5f5
--- /dev/null
+++ b/.idea/jpa-buddy.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..59780fe
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..35eb1dd
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/jumpit/.gitignore b/jumpit/.gitignore
index ed2e7b0..1779025 100644
--- a/jumpit/.gitignore
+++ b/jumpit/.gitignore
@@ -6,6 +6,8 @@ build/
!**/src/test/**/build/
*.yaml
+*.yaml
+
### STS ###
.apt_generated
.classpath
diff --git a/jumpit/src/main/java/org/sopt/jumpit/global/common/dto/message/ErrorMessage.java b/jumpit/src/main/java/org/sopt/jumpit/global/common/dto/message/ErrorMessage.java
index e8344dd..9d8c719 100644
--- a/jumpit/src/main/java/org/sopt/jumpit/global/common/dto/message/ErrorMessage.java
+++ b/jumpit/src/main/java/org/sopt/jumpit/global/common/dto/message/ErrorMessage.java
@@ -11,10 +11,12 @@ public enum ErrorMessage {
INTERNAL_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR.value(), "[ERROR] 서버 내부 오류가 발생하였습니다."),
COMPANY_NOT_FOUND_BY_ID_EXCEPTION(HttpStatus.NOT_FOUND.value(), "[ERROR] ID에 해당하는 기업이 없습니다."),
SKILL_NOT_FOUND_BY_ID_EXCEPTION(HttpStatus.NOT_FOUND.value(), "[ERROR] ID에 해당하는 기술스택이 없습니다."),
+ USER_NOT_FOUND_BY_ID_EXCEPTION(HttpStatus.NOT_FOUND.value(), "[ERROR] ID에 해당하는 유저를 찾을 수 없습니다."),
+ RESUME_NOT_FOUND_BY_ID_EXCEPTION(HttpStatus.NOT_FOUND.value(), "[ERROR] ID에 해당하는 이력서를 찾을 수 없습니다."),
CATEGORIES_NOT_FOUND_BY_POSITION_EXCEPTION(HttpStatus.NOT_FOUND.value(), "[ERROR] 포지션에 해당하는 카테고리가 없습니다."),
POSITION_NOT_FOUND_BY_CATEGORIES_EXCEPTION(HttpStatus.NOT_FOUND.value(), "[ERROR] 카테고리에 해당하는 포지션이 없습니다."),
POSITION_NOT_FOUND_EXCEPTION(HttpStatus.NOT_FOUND.value(), "[ERROR] ID에 해당하는 포지션이 없습니다."),
- PARSE_EXCEPTION(HttpStatus.BAD_REQUEST.value(), "[ERROR] JSON 파싱에 실패하였습니다."),
+ PARSE_EXCEPTION(HttpStatus.BAD_REQUEST.value(), "[ERROR] JSON 파싱에 실패하였습니다.")
;
private final int status;
diff --git a/jumpit/src/main/java/org/sopt/jumpit/global/common/dto/message/SuccessMessage.java b/jumpit/src/main/java/org/sopt/jumpit/global/common/dto/message/SuccessMessage.java
index 89ddc3d..b4e7d94 100644
--- a/jumpit/src/main/java/org/sopt/jumpit/global/common/dto/message/SuccessMessage.java
+++ b/jumpit/src/main/java/org/sopt/jumpit/global/common/dto/message/SuccessMessage.java
@@ -8,7 +8,10 @@
@Getter
public enum SuccessMessage {
SEARCH_COMPLETED_SUCCESS(HttpStatus.OK.value(), "[SUCCESS] 채용 공고 검색이 완료되었습니다."),
- FILTER_SEARCH_COMPLETED_SUCCESS(HttpStatus.OK.value(), "[SUCCESS] 채용 공고 필터 검색이 완료되었습니다.");
+ FILTER_SEARCH_COMPLETED_SUCCESS(HttpStatus.OK.value(), "[SUCCESS] 채용 공고 필터 검색이 완료되었습니다."),
+ RESUME_CREATED_COMPLETED_SUCCESS(HttpStatus.OK.value(), "[SUCCESS] 이력서 등록을 완료하였습니다."),
+ RESUME_SEARCH_COMPLETED_SUCCESS(HttpStatus.OK.value(), "[SUCCESS] 이력서 조회를 성공했습니다."),
+ RESUME_PRIVATE_CHANGE_COMPLETED_SUCCESS(HttpStatus.OK.value(), "[SUCCESS] 이력서 공개 범위 변경이 완료되었습니다.");
private final int status;
private final String message;
diff --git a/jumpit/src/main/java/org/sopt/jumpit/resume/controller/ResumeController.java b/jumpit/src/main/java/org/sopt/jumpit/resume/controller/ResumeController.java
new file mode 100644
index 0000000..06fbc3c
--- /dev/null
+++ b/jumpit/src/main/java/org/sopt/jumpit/resume/controller/ResumeController.java
@@ -0,0 +1,49 @@
+package org.sopt.jumpit.resume.controller;
+
+
+import lombok.RequiredArgsConstructor;
+import org.sopt.jumpit.global.common.dto.SuccessResponse;
+import org.sopt.jumpit.global.common.dto.message.SuccessMessage;
+import org.sopt.jumpit.resume.domain.Resume;
+import org.sopt.jumpit.resume.dto.ResumeCreateRequest;
+import org.sopt.jumpit.resume.dto.ResumePrivateRequest;
+import org.sopt.jumpit.resume.dto.ResumeSearchResponse;
+import org.sopt.jumpit.resume.service.ResumeService;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+
+import java.net.URI;
+
+@RestController
+@RequestMapping("/api/v1")
+@RequiredArgsConstructor
+public class ResumeController {
+ private final ResumeService resumeService;
+
+ @PostMapping("/resumes")
+ public ResponseEntity> createResume (
+ @RequestBody ResumeCreateRequest resumeCreateRequest
+ ) {
+ return ResponseEntity.status(HttpStatus.CREATED)
+ .header("Location", resumeService.createResume(resumeCreateRequest))
+ .body(SuccessResponse.of(SuccessMessage.RESUME_CREATED_COMPLETED_SUCCESS));
+ }
+
+ @GetMapping("/resumes/{userId}")
+ public ResponseEntity> findResumeById(@PathVariable Long userId) {
+ return ResponseEntity.status(HttpStatus.OK)
+ .body(SuccessResponse.of(SuccessMessage.RESUME_SEARCH_COMPLETED_SUCCESS,
+ resumeService.findResumeById(userId)));
+ }
+
+ @PatchMapping("/resumes/{resumeId}")
+ public ResponseEntity updateIsPrivate(
+ @PathVariable Long resumeId,
+ @RequestBody ResumePrivateRequest request
+ ) {
+ resumeService.updateResumePrivate(resumeId, request);
+ return ResponseEntity.status(HttpStatus.NO_CONTENT)
+ .body(SuccessResponse.of(SuccessMessage.RESUME_PRIVATE_CHANGE_COMPLETED_SUCCESS));
+ }
+}
diff --git a/jumpit/src/main/java/org/sopt/jumpit/resume/domain/Resume.java b/jumpit/src/main/java/org/sopt/jumpit/resume/domain/Resume.java
index 6fd34db..cec79e3 100644
--- a/jumpit/src/main/java/org/sopt/jumpit/resume/domain/Resume.java
+++ b/jumpit/src/main/java/org/sopt/jumpit/resume/domain/Resume.java
@@ -1,12 +1,20 @@
package org.sopt.jumpit.resume.domain;
import jakarta.persistence.*;
+import lombok.Builder;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import org.sopt.jumpit.resume.dto.ResumeCreateRequest;
import org.sopt.jumpit.user.domain.User;
import java.time.LocalDateTime;
@Entity
@Table(name = "Resume")
+@Getter
+@Setter
+@NoArgsConstructor
public class Resume {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@@ -28,4 +36,17 @@ public class Resume {
@Column(name = "createdAt")
private LocalDateTime createdAt;
+ @Builder
+ private Resume(User owner, String title) {
+ this.owner = owner;
+ this.title = title;
+ this.isPrivate = false;
+ }
+
+ public static Resume create(User owner, String title) {
+ return Resume.builder()
+ .title(title)
+ .owner(owner)
+ .build();
+ }
}
diff --git a/jumpit/src/main/java/org/sopt/jumpit/resume/dto/ResumeCreateRequest.java b/jumpit/src/main/java/org/sopt/jumpit/resume/dto/ResumeCreateRequest.java
new file mode 100644
index 0000000..a6d3cc7
--- /dev/null
+++ b/jumpit/src/main/java/org/sopt/jumpit/resume/dto/ResumeCreateRequest.java
@@ -0,0 +1,7 @@
+package org.sopt.jumpit.resume.dto;
+
+public record ResumeCreateRequest(
+ String title,
+ Long userId
+) {
+}
diff --git a/jumpit/src/main/java/org/sopt/jumpit/resume/dto/ResumePrivateRequest.java b/jumpit/src/main/java/org/sopt/jumpit/resume/dto/ResumePrivateRequest.java
new file mode 100644
index 0000000..adcdc0e
--- /dev/null
+++ b/jumpit/src/main/java/org/sopt/jumpit/resume/dto/ResumePrivateRequest.java
@@ -0,0 +1,6 @@
+package org.sopt.jumpit.resume.dto;
+
+public record ResumePrivateRequest(
+ Boolean isPrivate
+) {
+}
diff --git a/jumpit/src/main/java/org/sopt/jumpit/resume/dto/ResumeResponse.java b/jumpit/src/main/java/org/sopt/jumpit/resume/dto/ResumeResponse.java
new file mode 100644
index 0000000..9b2a5a7
--- /dev/null
+++ b/jumpit/src/main/java/org/sopt/jumpit/resume/dto/ResumeResponse.java
@@ -0,0 +1,29 @@
+package org.sopt.jumpit.resume.dto;
+
+import lombok.AccessLevel;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import org.sopt.jumpit.resume.domain.Resume;
+
+import java.time.LocalDateTime;
+
+@Builder(access = AccessLevel.PRIVATE)
+public record ResumeResponse(
+ Long id,
+ String title,
+ Boolean isPrivate,
+ LocalDateTime createdAt,
+ LocalDateTime modifiedAt
+) {
+
+ public static ResumeResponse of(Resume resume) {
+ return ResumeResponse.builder()
+ .id(resume.getId())
+ .title(resume.getTitle())
+ .isPrivate(resume.isPrivate())
+ .createdAt(resume.getCreatedAt())
+ .modifiedAt(resume.getModifiedAt())
+ .build();
+
+ }
+}
diff --git a/jumpit/src/main/java/org/sopt/jumpit/resume/dto/ResumeSearchResponse.java b/jumpit/src/main/java/org/sopt/jumpit/resume/dto/ResumeSearchResponse.java
new file mode 100644
index 0000000..a093acb
--- /dev/null
+++ b/jumpit/src/main/java/org/sopt/jumpit/resume/dto/ResumeSearchResponse.java
@@ -0,0 +1,23 @@
+package org.sopt.jumpit.resume.dto;
+
+import lombok.AccessLevel;
+import lombok.Builder;
+
+import java.util.List;
+
+@Builder(access = AccessLevel.PRIVATE)
+
+public record ResumeSearchResponse(
+ long userId,
+ List resumes
+) {
+
+ public static ResumeSearchResponse of(long userId, List resumes) {
+ return ResumeSearchResponse.builder()
+ .userId(userId)
+ .resumes(resumes)
+ .build();
+ }
+
+
+}
diff --git a/jumpit/src/main/java/org/sopt/jumpit/resume/repository/ResumeRepository.java b/jumpit/src/main/java/org/sopt/jumpit/resume/repository/ResumeRepository.java
index c8e9504..ff131ee 100644
--- a/jumpit/src/main/java/org/sopt/jumpit/resume/repository/ResumeRepository.java
+++ b/jumpit/src/main/java/org/sopt/jumpit/resume/repository/ResumeRepository.java
@@ -1,9 +1,14 @@
package org.sopt.jumpit.resume.repository;
import org.sopt.jumpit.resume.domain.Resume;
+import org.sopt.jumpit.resume.dto.ResumeResponse;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
+import java.util.List;
+import java.util.Optional;
+
@Repository
public interface ResumeRepository extends JpaRepository {
+ List findByOwnerId(Long userId);
}
diff --git a/jumpit/src/main/java/org/sopt/jumpit/resume/service/ResumeService.java b/jumpit/src/main/java/org/sopt/jumpit/resume/service/ResumeService.java
new file mode 100644
index 0000000..85eefad
--- /dev/null
+++ b/jumpit/src/main/java/org/sopt/jumpit/resume/service/ResumeService.java
@@ -0,0 +1,57 @@
+package org.sopt.jumpit.resume.service;
+
+import jakarta.transaction.Transactional;
+import lombok.RequiredArgsConstructor;
+import org.sopt.jumpit.global.common.dto.message.ErrorMessage;
+import org.sopt.jumpit.global.exception.NotFoundException;
+import org.sopt.jumpit.resume.domain.Resume;
+import org.sopt.jumpit.resume.dto.ResumeCreateRequest;
+import org.sopt.jumpit.resume.dto.ResumePrivateRequest;
+import org.sopt.jumpit.resume.dto.ResumeResponse;
+import org.sopt.jumpit.resume.dto.ResumeSearchResponse;
+import org.sopt.jumpit.resume.repository.ResumeRepository;
+import org.sopt.jumpit.user.domain.User;
+import org.sopt.jumpit.user.repository.UserRepository;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+@Service
+@RequiredArgsConstructor
+public class ResumeService {
+ private final ResumeRepository resumeRepository;
+ private final UserRepository userRepository;
+
+ @Transactional
+ public String createResume(
+ ResumeCreateRequest resumeCreateRequest
+ ) {
+ User findUser = userRepository.findById(resumeCreateRequest.userId()).orElseThrow(
+ () -> new NotFoundException(ErrorMessage.USER_NOT_FOUND_BY_ID_EXCEPTION)
+ );
+ return resumeRepository.save(Resume.create(findUser, "내 이력서")).getId().toString();
+ }
+
+ public ResumeSearchResponse findResumeById(Long userId) {
+ List resumes = resumeRepository.findByOwnerId(userId)
+ .stream()
+ .map(ResumeResponse::of)
+ .collect(Collectors.toList());
+ userRepository.findById(userId).orElseThrow(
+ () -> new NotFoundException(ErrorMessage.USER_NOT_FOUND_BY_ID_EXCEPTION)
+ );
+ return ResumeSearchResponse.of(userId, resumes);
+ }
+
+ @Transactional
+ public void updateResumePrivate(
+ Long resumeId,
+ ResumePrivateRequest resumePrivateRequest
+ ) {
+ Resume resume = resumeRepository.findById(resumeId).orElseThrow(
+ () -> new NotFoundException(ErrorMessage.RESUME_NOT_FOUND_BY_ID_EXCEPTION)
+ );
+ resume.setPrivate(resumePrivateRequest.isPrivate());
+ }
+}