Skip to content
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
@@ -0,0 +1,118 @@
package hongik.triple.apimodule.application.board;

import hongik.triple.commonmodule.dto.board.BoardReq;
import hongik.triple.commonmodule.dto.board.BoardRes;
import hongik.triple.domainmodule.domain.board.Board;
import hongik.triple.domainmodule.domain.board.repository.BoardRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class BoardService {

private final BoardRepository boardRepository;

/**
* 공지사항 등록
*/
@Transactional
public BoardRes registerBoard(BoardReq request) {
// Validation
validateBoardReq(request);

// Business Logic
Board board = Board.builder()
.title(request.title())
.content(request.content())
.build();

Board savedBoard = boardRepository.save(board);

// Response
return convertToBoardRes(savedBoard);
}

/**
* 공지사항 수정
*/
@Transactional
public BoardRes updateBoard(Long boardId, BoardReq request) {
// Validation
Board board = boardRepository.findById(boardId)
.orElseThrow(() -> new IllegalArgumentException("Board not found with id: " + boardId));

validateBoardReq(request);

// Business Logic
board.update(request.title(), request.content());

// Response
return convertToBoardRes(board);
}

/**
* 공지사항 삭제
*/
@Transactional
public void deleteBoard(Long boardId) {
// Validation
Board board = boardRepository.findById(boardId)
.orElseThrow(() -> new IllegalArgumentException("Board not found with id: " + boardId));

// Business Logic
boardRepository.delete(board);
}

/**
* 공지사항 단일 조회
*/
public BoardRes getBoard(Long boardId) {
// Validation
Board board = boardRepository.findById(boardId)
.orElseThrow(() -> new IllegalArgumentException("Board not found with id: " + boardId));

// Response
return convertToBoardRes(board);
}

/**
* 공지사항 페이지네이션 조회
*/
public Page<BoardRes> getBoardList(Pageable pageable) {
// Business Logic
Page<Board> boardPage = boardRepository.findAllByOrderByCreatedAtDesc(pageable);

// Response
return boardPage.map(this::convertToBoardRes);
}

/**
* BoardReq 유효성 검증
*/
private void validateBoardReq(BoardReq request) {
if (request.title() == null || request.title().trim().isEmpty()) {
throw new IllegalArgumentException("Title cannot be empty");
}
if (request.content() == null || request.content().trim().isEmpty()) {
throw new IllegalArgumentException("Content cannot be empty");
}
}

/**
* Board 엔티티를 BoardRes Record로 변환
*/
private BoardRes convertToBoardRes(Board board) {
return new BoardRes(
board.getBoardId(),
board.getTitle(),
board.getContent(),
board.getCreatedAt(),
board.getModifiedAt()
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
package hongik.triple.apimodule.presentation.board;

import hongik.triple.apimodule.application.board.BoardService;
import hongik.triple.apimodule.global.common.ApplicationResponse;
import hongik.triple.apimodule.global.security.PrincipalDetails;
import hongik.triple.commonmodule.dto.analysis.AnalysisRes;
import hongik.triple.commonmodule.dto.board.BoardReq;
import hongik.triple.commonmodule.dto.board.BoardRes;
import io.swagger.v3.oas.annotations.Operation;
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 lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.web.PageableDefault;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/api/v1/board")
@RequiredArgsConstructor
@Tag(name = "Board", description = "공지사항 관련 API")
public class BoardController {

private final BoardService boardService;

@PostMapping("/register")
@Operation(summary = "공지사항 등록", description = "공지사항을 등록합니다. (제목, 본문 두 가지 형태만 있으며, 이미지는 등록할 수 없습니다.)")
@ApiResponses(value = {
@ApiResponse(responseCode = "200",
description = "공지사항 등록 성공",
content = @Content(mediaType = "application/json",
schema = @Schema(implementation = BoardRes.class))),
@ApiResponse(responseCode = "400",
description = "잘못된 요청"),
@ApiResponse(responseCode = "500",
description = "서버 오류")
})
public ApplicationResponse<?> registerBoard(@RequestBody BoardReq request) {
BoardRes response = boardService.registerBoard(request);
return ApplicationResponse.ok(response);
}

@PutMapping("/{boardId}")
@Operation(summary = "공지사항 수정", description = "특정 공지사항을 수정합니다.")
@ApiResponses(value = {
@ApiResponse(responseCode = "200",
description = "공지사항 수정 성공",
content = @Content(mediaType = "application/json",
schema = @Schema(implementation = BoardRes.class))),
@ApiResponse(responseCode = "404",
description = "공지사항을 찾을 수 없음"),
@ApiResponse(responseCode = "500",
description = "서버 오류")
})
public ApplicationResponse<?> updateBoard(@PathVariable Long boardId, @RequestBody BoardReq request) {
BoardRes response = boardService.updateBoard(boardId, request);
return ApplicationResponse.ok(response);
}

@DeleteMapping("/{boardId}")
@Operation(summary = "공지사항 삭제", description = "특정 공지사항을 삭제합니다.")
@ApiResponses(value = {
@ApiResponse(responseCode = "200",
description = "공지사항 삭제 성공"),
@ApiResponse(responseCode = "404",
description = "공지사항을 찾을 수 없음"),
@ApiResponse(responseCode = "500",
description = "서버 오류")
})
public ApplicationResponse<?> deleteBoard(@PathVariable Long boardId) {
boardService.deleteBoard(boardId);
return ApplicationResponse.ok("공지사항이 삭제되었습니다.");
}

@GetMapping("/{boardId}")
@Operation(summary = "공지사항 단일 조회", description = "특정 공지사항을 조회합니다.")
@ApiResponses(value = {
@ApiResponse(responseCode = "200",
description = "공지사항 조회 성공",
content = @Content(mediaType = "application/json",
schema = @Schema(implementation = BoardRes.class))),
@ApiResponse(responseCode = "404",
description = "공지사항을 찾을 수 없음"),
@ApiResponse(responseCode = "500",
description = "서버 오류")
})
public ApplicationResponse<?> getBoard(@PathVariable Long boardId) {
BoardRes response = boardService.getBoard(boardId);
return ApplicationResponse.ok(response);
}

@GetMapping("/list")
@Operation(summary = "공지사항 목록 조회", description = "공지사항 목록을 페이지네이션으로 조회합니다.")
@ApiResponses(value = {
@ApiResponse(responseCode = "200",
description = "공지사항 목록 조회 성공"),
@ApiResponse(responseCode = "500",
description = "서버 오류")
})
public ApplicationResponse<?> getBoardList(
@PageableDefault(size = 10, sort = "createdAt", direction = Sort.Direction.DESC) Pageable pageable) {
Page<BoardRes> response = boardService.getBoardList(pageable);
return ApplicationResponse.ok(response);
}
}
Loading
Loading