Skip to content

Commit

Permalink
Merge pull request #228 from techeer-sv/BE/#222
Browse files Browse the repository at this point in the history
feat : Recruitment 도메인 CRUD 구현
  • Loading branch information
youKeon committed Oct 1, 2023
2 parents 27ea477 + c6dbd39 commit 3dd9fab
Show file tree
Hide file tree
Showing 28 changed files with 673 additions and 56 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,6 @@
@Builder
@NoArgsConstructor
@AllArgsConstructor
/*
* TODO
* Hard Delete 하기 위해서 제거해야 될 거 같아요
*/
@SQLDelete(sql = "UPDATE project SET is_deleted = true WHERE project_id = ?")
@Where(clause = "is_deleted = false")
public class Project extends BaseEntity {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,6 @@ public class ProjectTag {
@JoinColumn(name = "project_id")
private Project project;

/**
* tag는 FetchType.LAZY 필요 없나요??
*/
@ManyToOne
@JoinColumn(name = "tag_id")
private Tag tag;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
package com.graphy.backend.domain.project.domain;


import lombok.*;
import com.graphy.backend.domain.recruitment.domain.RecruitmentTag;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

import javax.persistence.*;
import java.util.Set;
Expand All @@ -23,4 +27,6 @@ public class Tag {
@OneToMany(mappedBy = "tag", cascade = CascadeType.ALL)
private Set<ProjectTag> projects;

@OneToMany(mappedBy = "tag", cascade = CascadeType.ALL)
private Set<RecruitmentTag> recruitments;
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import com.graphy.backend.domain.member.dto.response.GetMyPageResponse;
import com.graphy.backend.domain.member.service.MemberService;
import com.graphy.backend.domain.project.domain.Project;
import com.graphy.backend.domain.project.domain.Tag;
import com.graphy.backend.domain.project.domain.Tags;
import com.graphy.backend.domain.project.dto.request.CreateProjectRequest;
import com.graphy.backend.domain.project.dto.request.GetProjectPlanRequest;
Expand Down Expand Up @@ -67,7 +66,7 @@ public class ProjectService {
public CreateProjectResponse addProject(CreateProjectRequest dto, Member loginUser) {
Project entity = dto.toEntity(loginUser);
if (dto.getTechTags() != null) {
Tags foundTags = findTagListByName(dto.getTechTags());
Tags foundTags = tagService.findTagListByName(dto.getTechTags());
entity.addTag(foundTags);
}
Project project = projectRepository.save(entity);
Expand All @@ -87,7 +86,7 @@ public void removeProject(Long projectId) {
public UpdateProjectResponse modifyProject(Long projectId, UpdateProjectRequest dto) {
Project project = projectRepository.findById(projectId).get();
projectTagService.removeProjectTag(project.getId());
Tags updatedTags = findTagListByName(dto.getTechTags());
Tags updatedTags = tagService.findTagListByName(dto.getTechTags());

project.updateProject(dto.getProjectName(), dto.getContent(), dto.getDescription(), updatedTags, dto.getThumbNail());

Expand All @@ -103,12 +102,6 @@ public GetProjectDetailResponse findProjectById(Long projectId) {
return GetProjectDetailResponse.of(project, comments);
}

public Tags findTagListByName(List<String> techStacks) {
List<Tag> foundTags = techStacks.stream().map(tagService::findTagByTech)
.collect(Collectors.toList());
return new Tags(foundTags);
}

public List<GetProjectResponse> findProjectList(GetProjectsRequest dto, Pageable pageable) {
Page<Project> projects = projectRepository.searchProjectsWith(pageable, dto.getProjectName(), dto.getContent());
return GetProjectResponse.listOf(projects).getContent();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,28 @@
package com.graphy.backend.domain.project.service;

import com.graphy.backend.domain.project.domain.Tag;
import com.graphy.backend.domain.project.domain.Tags;
import com.graphy.backend.domain.project.repository.TagRepository;
import lombok.AccessLevel;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor(access = AccessLevel.PROTECTED)
public class TagService {

private final TagRepository tagRepository;

public Tags findTagListByName(List<String> techStacks) {
List<Tag> foundTags = techStacks.stream()
.map(this::findTagByTech)
.collect(Collectors.toList());
return new Tags(foundTags);
}

public Tag findTagByTech(String tech) {
return tagRepository.findTagByTech(tech);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,80 @@
package com.graphy.backend.domain.recruitment.controller;

import com.graphy.backend.domain.auth.util.annotation.CurrentUser;
import com.graphy.backend.domain.member.domain.Member;
import com.graphy.backend.domain.recruitment.domain.Position;
import com.graphy.backend.domain.recruitment.dto.request.CreateRecruitmentRequest;
import com.graphy.backend.domain.recruitment.dto.request.UpdateRecruitmentRequest;
import com.graphy.backend.domain.recruitment.dto.response.GetRecruitmentDetailResponse;
import com.graphy.backend.domain.recruitment.dto.response.GetRecruitmentResponse;
import com.graphy.backend.domain.recruitment.service.RecruitmentService;
import com.graphy.backend.global.common.PageRequest;
import com.graphy.backend.global.result.ResultCode;
import com.graphy.backend.global.result.ResultResponse;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.AccessLevel;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@Tag(name = "RecruitmentController", description = "프로젝트 구인 게시글 관련 API")
@RestController
@RequestMapping("api/v1/recruitments")
@RequiredArgsConstructor(access = AccessLevel.PROTECTED)
public class RecruitmentController {
private final RecruitmentService recruitmentService;

@Operation(summary = "createRecruitment", description = "구인 게시글 생성")
@PostMapping
public ResponseEntity<ResultResponse> recruitmentAdd(@Validated @RequestBody CreateRecruitmentRequest request,
@CurrentUser Member loginUser) {
recruitmentService.addRecruitment(request, loginUser);
return ResponseEntity.status(HttpStatus.CREATED)
.body(ResultResponse.of(ResultCode.RECRUITMENT_CREATE_SUCCESS));
}

@Operation(summary = "findRecruitment", description = "구인 게시글 상세 조회")
@GetMapping("/{recruitmentId}")
public ResponseEntity<ResultResponse> recruitmentDetails(@PathVariable Long recruitmentId) {
GetRecruitmentDetailResponse result = recruitmentService.findRecruitmentById(recruitmentId);
return ResponseEntity.ok(ResultResponse.of(ResultCode.RECRUITMENT_GET_SUCCESS, result));
}

@Operation(summary = "findRecruitmentList", description = "구인 게시글 조회")
@GetMapping
public ResponseEntity<ResultResponse> recruitmentList(@RequestParam(required = false) List<Position> positions,
@RequestParam(required = false) List<String> tags,
@RequestParam(required = false) String keyword,
PageRequest pageRequest) {
Pageable pageable = pageRequest.of();
List<GetRecruitmentResponse> result = recruitmentService.findRecruitmentList(positions, tags, keyword, pageable);
return ResponseEntity.ok(ResultResponse.of(ResultCode.RECRUITMENT_PAGING_GET_SUCCESS, result));
}

@Operation(summary = "updateRecruitment", description = "구인 게시글 수정")
@PutMapping("/{recruitmentId}")
public ResponseEntity<ResultResponse> RecruitmentModify(@PathVariable Long recruitmentId,
@RequestBody @Validated UpdateRecruitmentRequest request,
@CurrentUser Member loginUser) {
recruitmentService.modifyRecruitment(recruitmentId, request, loginUser);
return ResponseEntity.status(HttpStatus.NO_CONTENT)
.body(ResultResponse.of(ResultCode.RECRUITMENT_UPDATE_SUCCESS));
}

@Operation(summary = "deleteRecruitment", description = "구인 게시글 삭제(soft delete)")
@DeleteMapping("/{recruitmentId}")
public ResponseEntity<ResultResponse> recruitmentRemove(@PathVariable Long recruitmentId,
@CurrentUser Member loginUser) {
recruitmentService.removeRecruitment(recruitmentId, loginUser);
return ResponseEntity.status(HttpStatus.NO_CONTENT)
.body(ResultResponse.of(ResultCode.RECRUITMENT_DELETE_SUCCESS));
}
}


Original file line number Diff line number Diff line change
@@ -1,20 +1,27 @@
package com.graphy.backend.domain.recruitment.domain;

import com.graphy.backend.domain.member.domain.Member;
import com.graphy.backend.domain.project.domain.Tags;
import com.graphy.backend.domain.recruitment.dto.request.UpdateRecruitmentRequest;
import com.graphy.backend.global.common.BaseEntity;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.Where;

import javax.persistence.*;
import java.time.LocalDateTime;
import java.util.List;

@Entity
@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Where(clause = "is_deleted = false")
public class Recruitment extends BaseEntity {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
Expand Down Expand Up @@ -42,4 +49,34 @@ public class Recruitment extends BaseEntity {
@Enumerated(EnumType.STRING)
@Column(nullable = false)
private Position position;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "member_id")
private Member member;

@Embedded
private RecruitmentTags recruitmentTags;

public void addTag(Tags tags) {
recruitmentTags.add(this, tags);
}

public List<String> getTagNames() {
return this.recruitmentTags.getTagNames();
}

public List<Long> getTagIds() {
return this.recruitmentTags.getTagIds();
}

public void updateRecruitment(UpdateRecruitmentRequest request, Tags tags) {
this.title = request.getTitle();
this.content = request.getContent();
this.recruitmentCount = request.getRecruitmentCount();
this.type = request.getType();
this.endDate = request.getEndDate();
this.position = request.getPosition();
recruitmentTags.clear();
addTag(tags);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ public class RecruitmentTag {
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@ManyToOne(fetch = FetchType.LAZY)
@ManyToOne(cascade = CascadeType.PERSIST)
@JoinColumn(name = "recruitment_id")
private Recruitment recruitment;

@ManyToOne(fetch = FetchType.LAZY)
@ManyToOne
@JoinColumn(name = "tag_id")
private Tag tag;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ public void add(Recruitment recruitment, Tags tags) {
.forEach(tag -> value.add(new RecruitmentTag(recruitment, tag)));
}


public List<Long> getTagIds() {
return value.stream()
.map(recruitmentTag -> recruitmentTag.getTag().getId())
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package com.graphy.backend.domain.recruitment.dto.request;

import com.graphy.backend.domain.member.domain.Member;
import com.graphy.backend.domain.recruitment.domain.Position;
import com.graphy.backend.domain.recruitment.domain.ProcessType;
import com.graphy.backend.domain.recruitment.domain.Recruitment;
import com.graphy.backend.domain.recruitment.domain.RecruitmentTags;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Positive;
import java.time.LocalDateTime;
import java.util.List;

@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class CreateRecruitmentRequest {

@NotBlank(message = "Recruitment title cannot be blank")
private String title;

@NotBlank(message = "content cannot be blank")
private String content;

@NotNull(message = "ProcessType cannot be null")
private ProcessType type;

@NotNull(message = "endDate cannot be null")
private LocalDateTime endDate;

@NotNull(message = "period cannot be null")
private LocalDateTime period;

@NotNull(message = "position cannot be null")
private Position position;

@Positive(message = "최소 인원은 1명입니다.")
@NotNull(message = "recruitmentCount cannot be null")
private Integer recruitmentCount;

private List<String> techTags;

public Recruitment toEntity(Member member) {
return Recruitment.builder()
.member(member)
.title(title)
.content(content)
.type(type)
.endDate(endDate)
.period(period)
.position(position)
.recruitmentCount(recruitmentCount)
.recruitmentTags(new RecruitmentTags())
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package com.graphy.backend.domain.recruitment.dto.request;

import com.graphy.backend.domain.recruitment.domain.Position;
import com.graphy.backend.domain.recruitment.domain.ProcessType;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Positive;
import java.time.LocalDateTime;
import java.util.List;

@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class UpdateRecruitmentRequest {
@NotBlank(message = "Recruitment title cannot be blank")
private String title;

@NotBlank(message = "content cannot be blank")
private String content;

@NotNull(message = "ProcessType cannot be null")
private ProcessType type;

@NotNull(message = "endDate cannot be null")
private LocalDateTime endDate;

@NotNull(message = "period cannot be null")
private LocalDateTime period;

@NotNull(message = "position cannot be null")
private Position position;

@Positive(message = "최소 인원은 1명입니다.")
@NotNull(message = "recruitmentCount cannot be null")
private Integer recruitmentCount;

private List<String> techTags;
}
Loading

0 comments on commit 3dd9fab

Please sign in to comment.