Skip to content

Commit

Permalink
Merge pull request #16 from KUSITMS-CORECORD/feat/#13
Browse files Browse the repository at this point in the history
[Feat/#13] 폴더 CRUD 기능 구현
  • Loading branch information
daeun084 authored Oct 19, 2024
2 parents 784af7e + a670caf commit 991fd8e
Show file tree
Hide file tree
Showing 11 changed files with 304 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import corecord.dev.common.response.ApiResponse;
import corecord.dev.common.status.ErrorStatus;
import corecord.dev.domain.folder.exception.model.FolderException;
import corecord.dev.domain.token.exception.model.TokenException;
import corecord.dev.domain.user.exception.model.UserException;
import lombok.extern.slf4j.Slf4j;
Expand Down Expand Up @@ -29,6 +30,13 @@ public ResponseEntity<ApiResponse<Void>> handleTokenException(TokenException e)
return ApiResponse.error(e.getTokenErrorStatus());
}

// FolderException 처리
@ExceptionHandler(FolderException.class)
public ResponseEntity<ApiResponse<Void>> handleFolderException(FolderException e) {
log.warn(">>>>>>>>FolderException: {}", e.getFolderErrorStatus().getMessage());
return ApiResponse.error(e.getFolderErrorStatus());
}

// GeneralException 처리
@ExceptionHandler(GeneralException.class)
public ResponseEntity<ApiResponse<Void>> handleGeneralException(GeneralException e) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package corecord.dev.domain.folder.constant;

import corecord.dev.common.base.BaseSuccessStatus;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.springframework.http.HttpStatus;

@Getter
@AllArgsConstructor
public enum FolderSuccessStatus implements BaseSuccessStatus {

FOLDER_CREATE_SUCCESS(HttpStatus.CREATED, "S601", "폴더 생성이 성공적으로 완료되었습니다."),
FOLDER_DELETE_SUCCESS(HttpStatus.OK, "S601", "폴더 삭제 성공적으로 완료되었습니다."),
FOLDER_GET_SUCCESS(HttpStatus.OK, "S601", "폴더 리스트 조회가 성공적으로 완료되었습니다."),
FOLDER_UPDATE_SUCCESS(HttpStatus.OK, "S601", "폴더 수정이 성공적으로 완료되었습니다.");

private final HttpStatus httpStatus;
private final String code;
private final String message;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package corecord.dev.domain.folder.controller;

import corecord.dev.common.response.ApiResponse;
import corecord.dev.domain.folder.constant.FolderSuccessStatus;
import corecord.dev.domain.folder.dto.request.FolderRequest;
import corecord.dev.domain.folder.dto.response.FolderResponse;
import corecord.dev.domain.folder.service.FolderService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/folders")
public class FolderController {
private final FolderService folderService;

@PostMapping("")
public ResponseEntity<ApiResponse<FolderResponse.FolderDtoList>> createFolder(
@RequestBody FolderRequest.FolderDto folderDto
) {
FolderResponse.FolderDtoList folderResponse = folderService.createFolder(folderDto);

return ApiResponse.success(FolderSuccessStatus.FOLDER_CREATE_SUCCESS, folderResponse);
}

@DeleteMapping("/{folderId}")
public ResponseEntity<ApiResponse<FolderResponse.FolderDtoList>> deleteFolder(
@PathVariable(name = "folderId") Long folderId
) {
FolderResponse.FolderDtoList folderResponse = folderService.deleteFolder(folderId);

return ApiResponse.success(FolderSuccessStatus.FOLDER_DELETE_SUCCESS, folderResponse);
}

@GetMapping("")
public ResponseEntity<ApiResponse<FolderResponse.FolderDtoList>> getFolders(
) {
FolderResponse.FolderDtoList folderResponse = folderService.getFolderList();

return ApiResponse.success(FolderSuccessStatus.FOLDER_GET_SUCCESS, folderResponse);
}

@PatchMapping("")
public ResponseEntity<ApiResponse<FolderResponse.FolderDtoList>> updateFolder(
@RequestBody FolderRequest.FolderUpdateDto folderDto
) {
FolderResponse.FolderDtoList folderResponse = folderService.updateFolder(folderDto);

return ApiResponse.success(FolderSuccessStatus.FOLDER_UPDATE_SUCCESS, folderResponse);
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package corecord.dev.domain.folder.converter;

import corecord.dev.domain.folder.dto.response.FolderResponse;
import corecord.dev.domain.folder.entity.Folder;

import java.util.List;

public class FolderConverter {

public static Folder toFolderEntity(String title) {
return Folder.builder()
.title(title)
.build();
}

public static FolderResponse.FolderDto toFolderDto(Folder folder) {
return FolderResponse.FolderDto.builder()
.title(folder.getTitle())
.build();
}

public static FolderResponse.FolderDtoList toFolderDtoList(List<FolderResponse.FolderDto> folderDtoList) {
return FolderResponse.FolderDtoList.builder()
.folderDtoList(folderDtoList)
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package corecord.dev.domain.folder.dto.request;

import lombok.Data;

public class FolderRequest {

@Data
public static class FolderDto {
private String title;
}

@Data
public static class FolderUpdateDto {
private Long folderId;
private String title;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package corecord.dev.domain.folder.dto.response;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.Getter;

import java.util.List;

public class FolderResponse {

@Builder @Getter
@AllArgsConstructor @Data
public static class FolderDto {
private Long folderId;
private String title;
}

@Builder @Getter
@AllArgsConstructor @Data
public static class FolderDtoList {
private List<FolderDto> folderDtoList;
}
}
4 changes: 4 additions & 0 deletions src/main/java/corecord/dev/domain/folder/entity/Folder.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,8 @@ public class Folder extends BaseEntity {

@OneToOne(mappedBy = "folder")
private Record record;

public void updateTitle(String title) {
this.title = title;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package corecord.dev.domain.folder.exception.enums;

import corecord.dev.common.base.BaseErrorStatus;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.springframework.http.HttpStatus;

@Getter
@AllArgsConstructor
public enum FolderErrorStatus implements BaseErrorStatus {
DUPLICATED_FOLDER_TITLE(HttpStatus.BAD_REQUEST, "E0400_DUPLICATED_TITLE", "이미 존재하는 폴더 명입니다."),
OVERFLOW_FOLDER_TITLE(HttpStatus.BAD_REQUEST, "E0400_OVERFLOW_TITLE", "폴더 명은 15자 이내여야 합니다."),
FOLDER_NOT_FOUND(HttpStatus.NOT_FOUND, "E0404_FOLDER", "존재하지 않는 폴더입니다.");

private final HttpStatus httpStatus;
private final String code;
private final String message;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package corecord.dev.domain.folder.exception.model;

import corecord.dev.domain.folder.exception.enums.FolderErrorStatus;
import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor
public class FolderException extends RuntimeException {
private final FolderErrorStatus folderErrorStatus;

@Override
public String getMessage() {
return folderErrorStatus.getMessage();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package corecord.dev.domain.folder.repository;

import corecord.dev.domain.folder.dto.response.FolderResponse;
import corecord.dev.domain.folder.entity.Folder;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
public interface FolderRepository extends JpaRepository<Folder, Long> {

@Query("SELECT new corecord.dev.domain.folder.dto.response.FolderResponse$FolderDto(f.folderId, f.title) " +
"FROM Folder f " +
"ORDER BY f.createdAt")
List<FolderResponse.FolderDto> findFolderDtoList();

boolean existsByTitle(String title);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package corecord.dev.domain.folder.service;

import corecord.dev.domain.folder.converter.FolderConverter;
import corecord.dev.domain.folder.dto.request.FolderRequest;
import corecord.dev.domain.folder.dto.response.FolderResponse;
import corecord.dev.domain.folder.entity.Folder;
import corecord.dev.domain.folder.exception.enums.FolderErrorStatus;
import corecord.dev.domain.folder.exception.model.FolderException;
import corecord.dev.domain.folder.repository.FolderRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Service
@Slf4j
@RequiredArgsConstructor
public class FolderService {
private final FolderRepository folderRepository;

/*
* 폴더명(title)을 request로 받아, 새로운 폴더를 생성
* @param folderDto
* @return
*/
@Transactional
public FolderResponse.FolderDtoList createFolder(FolderRequest.FolderDto folderDto) {
validateDuplicatedFolderTitle(folderDto.getTitle());

Folder folder = FolderConverter.toFolderEntity(folderDto.getTitle());
folderRepository.save(folder);

return getFolderList();
}

/*
* folderId를 통해 folder을 삭제
* @param folderId
* @return
*/
@Transactional
public FolderResponse.FolderDtoList deleteFolder(Long folderId) {
Folder folder = findFolderById(folderId);
folderRepository.delete(folder);

return getFolderList();
}

/*
* folderId를 받아, 해당 folder의 title을 수정
* @param folderDto
* @return
*/
@Transactional
public FolderResponse.FolderDtoList updateFolder(FolderRequest.FolderUpdateDto folderDto) {
Folder folder = findFolderById(folderDto.getFolderId());

validateDuplicatedFolderTitle(folderDto.getTitle());
validateTitleLength(folderDto.getTitle());

folder.updateTitle(folderDto.getTitle());

return getFolderList();
}

/*
* 생성일 오름차순으로 폴더 리스트를 조회
* @return
*/
@Transactional(readOnly = true)
public FolderResponse.FolderDtoList getFolderList() {
List<FolderResponse.FolderDto> folderList = folderRepository.findFolderDtoList();
return FolderConverter.toFolderDtoList(folderList);
}

// 폴더명 중복 검사
private void validateDuplicatedFolderTitle(String title) {
if (folderRepository.existsByTitle(title)) {
throw new FolderException(FolderErrorStatus.DUPLICATED_FOLDER_TITLE);
}
}

// title 글자 수 검사
private void validateTitleLength(String title) {
if (title.length() > 15) {
throw new FolderException(FolderErrorStatus.OVERFLOW_FOLDER_TITLE);
}
}

private Folder findFolderById(Long folderId) {
return folderRepository.findById(folderId)
.orElseThrow(() -> new FolderException(FolderErrorStatus.FOLDER_NOT_FOUND));
}
}

0 comments on commit 991fd8e

Please sign in to comment.