Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FEAT] 구인글 관리 API 구현 #249

Merged
merged 5 commits into from
Apr 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import jakarta.validation.constraints.Min;
import org.springframework.web.bind.annotation.RequestParam;
import synk.meeteam.domain.recruitment.recruitment_post.dto.response.SimpleRecruitmentPostDto;
import synk.meeteam.domain.user.user.entity.User;
Expand All @@ -21,6 +23,8 @@ public interface PostManagementApi {
@Operation(summary = "북마크한 구인글 조회")
@SecurityRequirement(name = "Authorization")
PageNationDto<SimpleRecruitmentPostDto> getBookmarkPost(@AuthUser User user,
@RequestParam(value = "size", required = false, defaultValue = "24") @Valid @Min(1) int size,
@RequestParam(value = "page", required = false, defaultValue = "1") @Valid @Min(1) int page,
@RequestParam(value = "is-closed", required = false) Boolean isClosed);

@ApiResponses(
Expand All @@ -31,6 +35,8 @@ PageNationDto<SimpleRecruitmentPostDto> getBookmarkPost(@AuthUser User user,
@Operation(summary = "내가 신청한 구인글 조회")
@SecurityRequirement(name = "Authorization")
PageNationDto<SimpleRecruitmentPostDto> getAppliedPost(@AuthUser User user,
@RequestParam(value = "size", required = false, defaultValue = "24") @Valid @Min(1) int size,
@RequestParam(value = "page", required = false, defaultValue = "1") @Valid @Min(1) int page,
@RequestParam(value = "is-closed", required = false) Boolean isClosed);

@ApiResponses(
Expand All @@ -41,5 +47,7 @@ PageNationDto<SimpleRecruitmentPostDto> getAppliedPost(@AuthUser User user,
@Operation(summary = "내가 작성한 구인글 조회")
@SecurityRequirement(name = "Authorization")
PageNationDto<SimpleRecruitmentPostDto> getMyPost(@AuthUser User user,
@RequestParam(value = "size", required = false, defaultValue = "24") @Valid @Min(1) int size,
@RequestParam(value = "page", required = false, defaultValue = "1") @Valid @Min(1) int page,
@RequestParam(value = "is-closed", required = false) Boolean isClosed);
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
package synk.meeteam.domain.recruitment.recruitment_post.api;

import java.util.List;
import jakarta.validation.Valid;
import jakarta.validation.constraints.Min;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import synk.meeteam.domain.recruitment.recruitment_post.dto.response.SimpleRecruitmentPostDto;
import synk.meeteam.domain.recruitment.recruitment_post.service.RecruitmentPostService;
import synk.meeteam.domain.user.user.entity.User;
import synk.meeteam.global.dto.PageInfo;
import synk.meeteam.global.dto.PageNationDto;
import synk.meeteam.security.AuthUser;

Expand All @@ -17,60 +18,32 @@
@RequestMapping("/management")
public class PostManagementController implements PostManagementApi {

private final RecruitmentPostService recruitmentPostService;

@GetMapping("/bookmark")
@Override
public PageNationDto<SimpleRecruitmentPostDto> getBookmarkPost(@AuthUser User user,
@RequestParam(value = "size", required = false, defaultValue = "24") @Valid @Min(1) int size,
@RequestParam(value = "page", required = false, defaultValue = "1") @Valid @Min(1) int page,
@RequestParam(value = "is-closed", required = false) Boolean isClosed) {
return new PageNationDto<SimpleRecruitmentPostDto>(
List.of(new SimpleRecruitmentPostDto(
1L,
"같이할사람 구합니다.",
"프로젝트",
"goder",
"https://img.png",
"2021-12-15",
"교외",
true
)),
new PageInfo(1, 24, 1L, 1)
);
return recruitmentPostService.getBookmarkPost(size, page, user, isClosed);
}

@GetMapping("/applied")
@Override
public PageNationDto<SimpleRecruitmentPostDto> getAppliedPost(@AuthUser User user,
@RequestParam(value = "size", required = false, defaultValue = "24") @Valid @Min(1) int size,
@RequestParam(value = "page", required = false, defaultValue = "1") @Valid @Min(1) int page,
@RequestParam(value = "is-closed", required = false) Boolean isClosed) {
return new PageNationDto<SimpleRecruitmentPostDto>(
List.of(new SimpleRecruitmentPostDto(
1L,
"같이할사람 구합니다.",
"프로젝트",
"goder",
"https://img.png",
"2021-12-15",
"교외",
true
)),
new PageInfo(1, 24, 1L, 1)
);
return recruitmentPostService.getAppliedPost(size, page, user, isClosed);
}

@GetMapping("/myPost")
@Override
public PageNationDto<SimpleRecruitmentPostDto> getMyPost(@AuthUser User user,
@RequestParam(value = "size", required = false, defaultValue = "24") @Valid @Min(1) int size,
@RequestParam(value = "page", required = false, defaultValue = "1") @Valid @Min(1) int page,
@RequestParam(value = "is-closed", required = false) Boolean isClosed) {
return new PageNationDto<SimpleRecruitmentPostDto>(
List.of(new SimpleRecruitmentPostDto(
1L,
"같이할사람 구합니다.",
"프로젝트",
"goder",
"https://img.png",
"2021-12-15",
"교외",
true
)),
new PageInfo(1, 24, 1L, 1)
);
return recruitmentPostService.getMyPost(size, page, user, isClosed);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,8 @@
public interface SimpleRecruitmentPostMapper {
@Mapping(target = "category", expression = "java(recruitmentPostVo.getCategory().getName())")
@Mapping(target = "scope", expression = "java(recruitmentPostVo.getScope().getName())")
SimpleRecruitmentPostDto toSimpleRecruitmentPostDto(RecruitmentPostVo recruitmentPostVo);
@Mapping(target = "writerProfileImg", source = "writerProfileImg")
@Mapping(target = "writerId", source = "writerId")
SimpleRecruitmentPostDto toSimpleRecruitmentPostDto(RecruitmentPostVo recruitmentPostVo, String writerId,
String writerProfileImg);
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ public record SimpleRecruitmentPostDto(
String title,
@Schema(description = "유형", example = "프로젝트")
String category,
@Schema(description = "작성자 id", example = "sdfkljwncxmv")
String writerId,
@Schema(description = "작성자 닉네임", example = "song123")
String writerNickname,
@Schema(description = "작성자 사진", example = "url 형태")
Expand All @@ -18,6 +20,8 @@ public record SimpleRecruitmentPostDto(
@Schema(description = "범위", example = "교내")
String scope,
@Schema(description = "북마크 여부", example = "true")
Boolean isBookmarked
Boolean isBookmarked,
@Schema(description = "마감 여부", example = "true")
Boolean isClosed
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package synk.meeteam.domain.recruitment.recruitment_post.repository;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import synk.meeteam.domain.recruitment.recruitment_post.repository.vo.RecruitmentPostVo;
import synk.meeteam.domain.user.user.entity.User;

public interface RecruitmentManagementRepository {
Page<RecruitmentPostVo> findMyBookmarkPost(Pageable pageable, User user, Boolean isClosed);

Page<RecruitmentPostVo> findMyAppliedPost(Pageable pageable, User user, Boolean isClosed);

Page<RecruitmentPostVo> findMyPost(Pageable pageable, User user, Boolean isClosed);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
package synk.meeteam.domain.recruitment.recruitment_post.repository;

import static synk.meeteam.domain.recruitment.bookmark.entity.QBookmark.bookmark;
import static synk.meeteam.domain.recruitment.recruitment_applicant.entity.QRecruitmentApplicant.recruitmentApplicant;
import static synk.meeteam.domain.recruitment.recruitment_post.entity.QRecruitmentPost.recruitmentPost;
import static synk.meeteam.domain.recruitment.recruitment_post.repository.expression.ExpressionUtils.isClosedEq;

import com.querydsl.core.types.dsl.Expressions;
import com.querydsl.jpa.impl.JPAQuery;
import com.querydsl.jpa.impl.JPAQueryFactory;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.support.PageableExecutionUtils;
import org.springframework.stereotype.Repository;
import synk.meeteam.domain.recruitment.recruitment_post.repository.vo.QRecruitmentPostVo;
import synk.meeteam.domain.recruitment.recruitment_post.repository.vo.RecruitmentPostVo;
import synk.meeteam.domain.user.user.entity.QUser;
import synk.meeteam.domain.user.user.entity.User;

@Repository
@RequiredArgsConstructor
public class RecruitmentManagementRepositoryImpl implements RecruitmentManagementRepository {
private final JPAQueryFactory queryFactory;

@Override
public Page<RecruitmentPostVo> findMyBookmarkPost(Pageable pageable, User user, Boolean isClosed) {
List<RecruitmentPostVo> contents = getBookmarkPostVos(pageable, user, isClosed);
JPAQuery<Long> countQuery = getBookmarkCount(user, isClosed);
return PageableExecutionUtils.getPage(contents, pageable, countQuery::fetchOne);
}

@Override
public Page<RecruitmentPostVo> findMyAppliedPost(Pageable pageable, User user, Boolean isClosed) {
List<RecruitmentPostVo> contents = getAppliedPostVos(pageable, user, isClosed);
JPAQuery<Long> countQuery = getAppliedCount(user, isClosed);
return PageableExecutionUtils.getPage(contents, pageable, countQuery::fetchOne);
}

@Override
public Page<RecruitmentPostVo> findMyPost(Pageable pageable, User user, Boolean isClosed) {
List<RecruitmentPostVo> contents = getMyPostVos(pageable, user, isClosed);
JPAQuery<Long> countQuery = getMyPostCount(user, isClosed);
return PageableExecutionUtils.getPage(contents, pageable, countQuery::fetchOne);
}

private List<RecruitmentPostVo> getBookmarkPostVos(Pageable pageable, User userDomain, Boolean isClosed) {
QUser writer = new QUser("writer");

JPAQuery<RecruitmentPostVo> query = queryFactory.select(
new QRecruitmentPostVo(
recruitmentPost.id,
recruitmentPost.title,
recruitmentPost.category,
recruitmentPost.scope,
writer.id,
writer.nickname,
writer.profileImgFileName,
recruitmentPost.deadline,
Expressions.asBoolean(true),
recruitmentPost.createdAt,
recruitmentPost.isClosed
)
)
.distinct()
.from(recruitmentPost)
.leftJoin(writer).on(recruitmentPost.createdBy.eq(writer.id))
.leftJoin(bookmark).on(recruitmentPost.id.eq(bookmark.recruitmentPost.id))
.where(
isClosedEq(isClosed),
bookmark.user.id.eq(userDomain.getId())
);

return query.orderBy(recruitmentPost.createdAt.desc(), recruitmentPost.id.desc())
.offset(pageable.getOffset()) //페이지 번호
.limit(pageable.getPageSize()) //페이지 사이즈
.fetch();
}

private List<RecruitmentPostVo> getAppliedPostVos(Pageable pageable, User userDomain, Boolean isClosed) {
QUser writer = new QUser("writer");

JPAQuery<RecruitmentPostVo> query = queryFactory.select(
new QRecruitmentPostVo(
recruitmentPost.id,
recruitmentPost.title,
recruitmentPost.category,
recruitmentPost.scope,
writer.id,
writer.nickname,
writer.profileImgFileName,
recruitmentPost.deadline,
Expressions.asBoolean(true),
recruitmentPost.createdAt,
recruitmentPost.isClosed
)
)
.distinct()
.from(recruitmentPost)
.leftJoin(writer).on(recruitmentPost.createdBy.eq(writer.id))
.leftJoin(recruitmentApplicant).on(recruitmentPost.id.eq(recruitmentApplicant.recruitmentPost.id))
.where(
isClosedEq(isClosed),
recruitmentApplicant.applicant.id.eq(userDomain.getId())
);

return query.orderBy(recruitmentPost.createdAt.desc(), recruitmentPost.id.desc())
.offset(pageable.getOffset()) //페이지 번호
.limit(pageable.getPageSize()) //페이지 사이즈
.fetch();
}

private List<RecruitmentPostVo> getMyPostVos(Pageable pageable, User userDomain, Boolean isClosed) {
QUser writer = new QUser("writer");

JPAQuery<RecruitmentPostVo> query = queryFactory.select(
new QRecruitmentPostVo(
recruitmentPost.id,
recruitmentPost.title,
recruitmentPost.category,
recruitmentPost.scope,
writer.id,
writer.nickname,
writer.profileImgFileName,
recruitmentPost.deadline,
Expressions.asBoolean(true),
recruitmentPost.createdAt,
recruitmentPost.isClosed
)
)
.distinct()
.from(recruitmentPost)
.leftJoin(writer).on(recruitmentPost.createdBy.eq(writer.id))
.where(
isClosedEq(isClosed),
writer.id.eq(userDomain.getId())
);

return query.orderBy(recruitmentPost.createdAt.desc(), recruitmentPost.id.desc())
.offset(pageable.getOffset()) //페이지 번호
.limit(pageable.getPageSize()) //페이지 사이즈
.fetch();
}

private JPAQuery<Long> getBookmarkCount(User userDomain, Boolean isClosed) {
QUser writer = new QUser("writer");

return queryFactory.select(recruitmentPost.countDistinct())
.from(recruitmentPost)
.leftJoin(writer).on(recruitmentPost.createdBy.eq(writer.id))
.leftJoin(bookmark).on(recruitmentPost.id.eq(bookmark.recruitmentPost.id))
.where(
isClosedEq(isClosed),
bookmark.user.id.eq(userDomain.getId())
);
}

private JPAQuery<Long> getAppliedCount(User userDomain, Boolean isClosed) {
QUser writer = new QUser("writer");

return queryFactory.select(recruitmentPost.countDistinct())
.from(recruitmentPost)
.leftJoin(writer).on(recruitmentPost.createdBy.eq(writer.id))
.leftJoin(recruitmentApplicant).on(recruitmentPost.id.eq(recruitmentApplicant.recruitmentPost.id))
.where(
isClosedEq(isClosed),
recruitmentApplicant.applicant.id.eq(userDomain.getId())
);
}

private JPAQuery<Long> getMyPostCount(User userDomain, Boolean isClosed) {
QUser writer = new QUser("writer");

return queryFactory.select(recruitmentPost.countDistinct())
.from(recruitmentPost)
.leftJoin(writer).on(recruitmentPost.createdBy.eq(writer.id))
.where(
isClosedEq(isClosed),
writer.id.eq(userDomain.getId())
);
}
Goder-0 marked this conversation as resolved.
Show resolved Hide resolved

}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import synk.meeteam.domain.recruitment.recruitment_post.exception.RecruitmentPostException;

public interface RecruitmentPostRepository extends JpaRepository<RecruitmentPost, Long>,
RecruitmentPostSearchRepository {
RecruitmentPostSearchRepository, RecruitmentManagementRepository {

default RecruitmentPost findByIdOrElseThrow(Long postId) {
return findById(postId).orElseThrow(() -> new RecruitmentPostException(NOT_FOUND_POST));
Expand Down
Loading
Loading