Skip to content

Commit

Permalink
✨ Feat: 전체/내 프로젝트 조회, 프로젝트 상세 페이지 조회 API 개발
Browse files Browse the repository at this point in the history
  • Loading branch information
HyoBN committed Jan 30, 2024
1 parent 6fa1e40 commit 09378fe
Show file tree
Hide file tree
Showing 8 changed files with 256 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,14 @@ public enum ResponseStatus implements BaseCode {
// member 에러
MEMBER_NOT_FOUND(OK, 2200, "존재하지 않는 유저입니다."),

// test 에러
// Peertest 에러
UUID_NOT_FOUND(OK, 2250, "잘못된 UUID 값입니다."),

// Project 에러
PROJECT_NOT_FOUND(OK, 2300, "존재하지 않는 프로젝트입니다."),
PROJECT_COUNT_ZERO(OK, 2301, "프로젝트가 존재하지 않습니다."),


// 400번대 에러

_UNAUTHORIZED(UNAUTHORIZED,4001,"로그인이 필요합니다."),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package cmc.peerna.apiResponse.exception.handler;

import cmc.peerna.apiResponse.code.ResponseStatus;
import cmc.peerna.apiResponse.exception.GeneralException;

public class ProjectException extends GeneralException {

public ProjectException(ResponseStatus code){
super(code);
}
}
57 changes: 57 additions & 0 deletions src/main/java/cmc/peerna/converter/ProjectConverter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package cmc.peerna.converter;

import cmc.peerna.domain.Member;
import cmc.peerna.domain.Project;
import cmc.peerna.service.MemberService;
import cmc.peerna.service.ProjectService;
import cmc.peerna.web.dto.responseDto.MemberResponseDto;
import cmc.peerna.web.dto.responseDto.ProjectResponseDto;
import cmc.peerna.web.dto.responseDto.RootResponseDto;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;

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

@RequiredArgsConstructor
public class ProjectConverter {
public static ProjectResponseDto.ProjectDetailDto toProjectDetailDto(Project project) {
return ProjectResponseDto.ProjectDetailDto.builder()
.projectId(project.getId())
.projectName(project.getName())
.introduce(project.getIntroduce())
.startDate(project.getStartDate())
.endDate(project.getEndDate())
.openChattingLink(project.getOpenChattingLink())
.notionLink(project.getNotionLink())
.githubLink(project.getGithubLink())
.creatorSimpleProfileDto(MemberConverter.toMemberSimpleProfileDto(project.getCreator()))
.build();
}

public static ProjectResponseDto.ProjectSimpleProfileDto toProjectSimpleProfile(Project project) {
return ProjectResponseDto.ProjectSimpleProfileDto.builder()
.projectId(project.getId())
.projectName(project.getName())
.introduce(project.getIntroduce())
.startDate(project.getStartDate())
.endDate(project.getEndDate())
.build();
}

public static ProjectResponseDto.ProjectPageDto toProjectPageDto(Page<Project> projectPage) {
if(projectPage.getTotalElements()==0L) return null;
List<ProjectResponseDto.ProjectSimpleProfileDto> projectSimpleProfileDtoList = projectPage.stream()
.map(project -> toProjectSimpleProfile(project))
.collect(Collectors.toList());

return ProjectResponseDto.ProjectPageDto.builder()
.projectList(projectSimpleProfileDtoList)
.isFirst(projectPage.isFirst())
.isLast(projectPage.isLast())
.totalPage(projectPage.getTotalPages())
.totalElements(projectPage.getTotalElements())
.currentPageElements(projectPage.getNumberOfElements())
.build();
}
}
7 changes: 7 additions & 0 deletions src/main/java/cmc/peerna/repository/ProjectRepository.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
package cmc.peerna.repository;

import cmc.peerna.domain.Member;
import cmc.peerna.domain.Project;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.jpa.repository.JpaRepository;

public interface ProjectRepository extends JpaRepository<Project, Long> {

Page<Project> findAllByIdNotNull(PageRequest pageRequest);

Page<Project> findAllByCreator(Member creator, PageRequest pageRequest);
}
8 changes: 8 additions & 0 deletions src/main/java/cmc/peerna/service/ProjectService.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
package cmc.peerna.service;

import cmc.peerna.domain.Member;
import cmc.peerna.domain.Project;
import cmc.peerna.web.dto.requestDto.ProjectRequestDto;
import cmc.peerna.web.dto.responseDto.ProjectResponseDto;

public interface ProjectService {
void newProject(Member member, ProjectRequestDto.ProjectCreateDto request);
Project findById(Long projectId);

ProjectResponseDto.ProjectDetailDto getProjectDetailInfo(Long projectId);

ProjectResponseDto.ProjectPageDto getAllProject(Integer page);
ProjectResponseDto.ProjectPageDto getMyProject(Member member, Integer page);
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,22 @@
package cmc.peerna.service.serviceImpl;

import cmc.peerna.apiResponse.code.ResponseStatus;
import cmc.peerna.apiResponse.exception.handler.MemberException;
import cmc.peerna.apiResponse.exception.handler.ProjectException;
import cmc.peerna.apiResponse.exception.handler.RootException;
import cmc.peerna.converter.ProjectConverter;
import cmc.peerna.domain.Member;
import cmc.peerna.domain.Project;
import cmc.peerna.repository.ProjectRepository;
import cmc.peerna.service.ProjectService;
import cmc.peerna.web.dto.requestDto.ProjectRequestDto;
import cmc.peerna.web.dto.responseDto.ProjectResponseDto;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

Expand All @@ -15,6 +25,8 @@
@RequiredArgsConstructor
public class ProjectServiceImpl implements ProjectService {
private final ProjectRepository projectRepository;
@Value("${paging.size}")
private Integer pageSize;

@Override
@Transactional
Expand All @@ -31,4 +43,47 @@ public void newProject(Member member, ProjectRequestDto.ProjectCreateDto request
.build();
projectRepository.save(project);
}

@Override
public Project findById(Long projectId) {
Project project = projectRepository.findById(projectId).orElseThrow(() -> new ProjectException(ResponseStatus.PROJECT_NOT_FOUND));
return project;

}
@Override
public ProjectResponseDto.ProjectDetailDto getProjectDetailInfo(Long projectId) {
Project project = findById(projectId);
return ProjectConverter.toProjectDetailDto(project);
}

@Override
public ProjectResponseDto.ProjectPageDto getAllProject(Integer page) {
PageRequest pageRequest = PageRequest.of(page, pageSize, Sort.by(Sort.Order.desc("startDate"), Sort.Order.asc("name")));

Page<Project> allProjectPage = projectRepository.findAllByIdNotNull(pageRequest);
if (allProjectPage.getTotalElements() == 0L) {
throw new RootException(ResponseStatus.PROJECT_COUNT_ZERO);
}
if (allProjectPage.getTotalPages() <= page)
throw new MemberException(ResponseStatus.OVER_PAGE_INDEX_ERROR);

ProjectResponseDto.ProjectPageDto allProjectPageDto = ProjectConverter.toProjectPageDto(allProjectPage);
return allProjectPageDto;
}

@Override
public ProjectResponseDto.ProjectPageDto getMyProject(Member member, Integer page) {
PageRequest pageRequest = PageRequest.of(page, pageSize, Sort.by(Sort.Order.desc("startDate"), Sort.Order.asc("name")));

Page<Project> allProjectPage = projectRepository.findAllByCreator(member, pageRequest);
if (allProjectPage.getTotalElements() == 0L) {
throw new RootException(ResponseStatus.PROJECT_COUNT_ZERO);
}
if (allProjectPage.getTotalPages() <= page)
throw new MemberException(ResponseStatus.OVER_PAGE_INDEX_ERROR);

ProjectResponseDto.ProjectPageDto allProjectPageDto = ProjectConverter.toProjectPageDto(allProjectPage);
return allProjectPageDto;
}

}
65 changes: 60 additions & 5 deletions src/main/java/cmc/peerna/web/controller/ProjectController.java
Original file line number Diff line number Diff line change
@@ -1,40 +1,42 @@
package cmc.peerna.web.controller;

import cmc.peerna.apiResponse.code.ResponseStatus;
import cmc.peerna.apiResponse.exception.handler.MemberException;
import cmc.peerna.apiResponse.response.ResponseDto;
import cmc.peerna.converter.MemberConverter;
import cmc.peerna.domain.Member;
import cmc.peerna.jwt.handler.annotation.AuthMember;
import cmc.peerna.service.ProjectService;
import cmc.peerna.validation.annotation.CheckPage;
import cmc.peerna.web.dto.requestDto.MemberRequestDto;
import cmc.peerna.web.dto.requestDto.ProjectRequestDto;
import cmc.peerna.web.dto.responseDto.MemberResponseDto;
import cmc.peerna.web.dto.responseDto.ProjectResponseDto;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;

@RestController
@Slf4j
@Validated
@RequiredArgsConstructor
@ApiResponses({
@ApiResponse(responseCode = "2000", description = "OK 성공"),
@ApiResponse(responseCode = "4007", description = "feign에서 400번대 에러가 발생했습니다. 코드값이 잘못되었거나 이미 해당 코드를 통해 토큰 요청을 한 경우.\""),
@ApiResponse(responseCode = "4008", description = "토큰이 올바르지 않습니다."),
@ApiResponse(responseCode = "4009", description = "리프레쉬 토큰이 유효하지 않습니다. 다시 로그인 해주세요"),
@ApiResponse(responseCode = "4010", description = "기존 토큰이 만료되었습니다. 토큰을 재발급해주세요."),
@ApiResponse(responseCode = "4011", description = "모든 토큰이 만료되었습니다. 다시 로그인해주세요."),
@ApiResponse(responseCode = "5000", description = "서버 에러, 로빈에게 알려주세요."),

})
@Tag(name = "Project 관련 API 목록", description = "Project 관련 API 목록입니다.")

Expand All @@ -50,4 +52,57 @@ public ResponseDto<MemberResponseDto.MemberStatusDto> saveMemberInfo(@AuthMember
projectService.newProject(member, request);
return ResponseDto.of(MemberConverter.toMemberStatusDto(member.getId(), "프로젝트 생성 완료"));
}

@Operation(summary = "전체 프로젝트 조회 API ✔️🔑", description = "전체 프로젝트 조회 API입니다.")
@ApiResponses({
@ApiResponse(responseCode = "4012", description = "BAD_REQUEST , 페이지 번호는 1 이상이여야 합니다.", content = @Content(schema = @Schema(implementation = ResponseDto.class))),
@ApiResponse(responseCode = "4013", description = "BAD_REQUEST , 페이지 번호가 페이징 범위를 초과했습니다.", content = @Content(schema = @Schema(implementation = ResponseDto.class))),
@ApiResponse(responseCode = "2301", description = "OK , 프로젝트가 존재하지 않습니다.", content = @Content(schema = @Schema(implementation = ResponseDto.class))),
})
@Parameters({
@Parameter(name = "member", hidden = true)

})
@GetMapping("/project")
public ResponseDto<ProjectResponseDto.ProjectPageDto> getAllProject(@AuthMember Member member, @CheckPage @RequestParam(name = "page") Integer page) {
if (page == null)
page = 1;
else if (page < 1)
throw new MemberException(ResponseStatus.UNDER_PAGE_INDEX_ERROR);
page -= 1;

ProjectResponseDto.ProjectPageDto allProject = projectService.getAllProject(page);
return ResponseDto.of(allProject);
}

@Operation(summary = "내 프로젝트 조회 API ✔️🔑", description = "내 프로젝트 조회 API입니다.")
@ApiResponses({
@ApiResponse(responseCode = "4012", description = "BAD_REQUEST , 페이지 번호는 1 이상이여야 합니다.", content = @Content(schema = @Schema(implementation = ResponseDto.class))),
@ApiResponse(responseCode = "4013", description = "BAD_REQUEST , 페이지 번호가 페이징 범위를 초과했습니다.", content = @Content(schema = @Schema(implementation = ResponseDto.class))),
@ApiResponse(responseCode = "2301", description = "OK , 프로젝트가 존재하지 않습니다.", content = @Content(schema = @Schema(implementation = ResponseDto.class))),
})
@Parameters({
@Parameter(name = "member", hidden = true)
})
@GetMapping("/project/my")
public ResponseDto<ProjectResponseDto.ProjectPageDto> getMyProject(@AuthMember Member member, @CheckPage @RequestParam(name = "page") Integer page) {
if (page == null)
page = 1;
else if (page < 1)
throw new MemberException(ResponseStatus.UNDER_PAGE_INDEX_ERROR);
page -= 1;

ProjectResponseDto.ProjectPageDto allProject = projectService.getMyProject(member, page);
return ResponseDto.of(allProject);
}

@Operation(summary = "프로젝트 상세 페이지 조회 API ✔️🔑", description = "프로젝트 상세 페이지 조회 API입니다.")
@Parameters({
@Parameter(name = "member", hidden = true)
})
@GetMapping("/project/{project-id}")
public ResponseDto<ProjectResponseDto.ProjectDetailDto> getProjectDetail(@AuthMember Member member, @PathVariable(name = "project-id") Long projectId) {
ProjectResponseDto.ProjectDetailDto projectDetailInfo = projectService.getProjectDetailInfo(projectId);
return ResponseDto.of(projectDetailInfo);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package cmc.peerna.web.dto.responseDto;

import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
import lombok.*;

import java.sql.Date;
import java.util.List;

public class ProjectResponseDto {

@Builder
@Getter
@AllArgsConstructor(access = AccessLevel.PROTECTED)
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public static class ProjectDetailDto{
private Long projectId;
private String projectName;
private String introduce;
private Date startDate;
private Date endDate;
private String openChattingLink;
private String notionLink;
private String githubLink;
private MemberResponseDto.memberSimpleProfileDto creatorSimpleProfileDto;
}

@Builder
@Getter
@AllArgsConstructor(access = AccessLevel.PROTECTED)
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public static class ProjectSimpleProfileDto{
private Long projectId;
private String projectName;
private String introduce;
private Date startDate;
private Date endDate;
}

@Builder
@Getter
@AllArgsConstructor(access = AccessLevel.PROTECTED)
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public static class ProjectPageDto{
List<ProjectSimpleProfileDto> projectList;
Long totalElements;
Integer currentPageElements;
Integer totalPage;
Boolean isFirst;
Boolean isLast;
}
}

0 comments on commit 09378fe

Please sign in to comment.