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/190] 끌올 기능 API 구현 #191

Merged
merged 2 commits into from
Feb 4, 2025
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 @@ -7,6 +7,7 @@
import com.gamegoo.gamegoo_v2.account.member.domain.Tier;
import com.gamegoo.gamegoo_v2.content.board.dto.request.BoardInsertRequest;
import com.gamegoo.gamegoo_v2.content.board.dto.request.BoardUpdateRequest;
import com.gamegoo.gamegoo_v2.content.board.dto.response.BoardBumpResponse;
import com.gamegoo.gamegoo_v2.content.board.dto.response.BoardByIdResponse;
import com.gamegoo.gamegoo_v2.content.board.dto.response.BoardByIdResponseForMember;
import com.gamegoo.gamegoo_v2.content.board.dto.response.BoardInsertResponse;
Expand Down Expand Up @@ -124,4 +125,16 @@ public ApiResponse<MyBoardResponse> getMyBoardList(@ValidPage @RequestParam(name
return ApiResponse.ok(boardFacadeService.getMyBoardList(member, page));
}

/**
* 게시글 끌올(bump) API
* 사용자가 "끌올" 버튼을 누르면 해당 게시글의 bumpTime이 업데이트되어 상단으로 노출됩니다.
*/
@PostMapping("/{boardId}/bump")
@Operation(summary = "게시글 끌올 API", description = "게시글을 끌올하여 상단 노출시키는 API 입니다. 마지막 끌올 후 1시간 제한이 적용됩니다.")
@Parameter(name = "boardId", description = "끌올할 게시판 글 id 입니다.")
public ApiResponse<BoardBumpResponse> bumpBoard(@PathVariable Long boardId,
@AuthMember Member member) {
return ApiResponse.ok(boardFacadeService.bumpBoard(boardId, member));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.Formula;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

Expand Down Expand Up @@ -71,6 +73,11 @@ public class Board extends BaseDateTimeEntity {
@OneToMany(mappedBy = "board", cascade = CascadeType.PERSIST, orphanRemoval = true)
private List<BoardGameStyle> boardGameStyles = new ArrayList<>();

private LocalDateTime bumpTime;

@Formula("GREATEST(COALESCE(bump_time, created_at), created_at)")
private LocalDateTime activityTime;


public static Board create(Member member, GameMode gameMode, Position mainP, Position subP,
Position wantP,
Expand Down Expand Up @@ -143,5 +150,13 @@ public void setDeleted(boolean deleted) {
this.deleted = deleted;
}

public void bump(LocalDateTime bumpTime) {
this.bumpTime = bumpTime;
}

public LocalDateTime getActivityTime() {
return activityTime;
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.gamegoo.gamegoo_v2.content.board.dto.response;

import lombok.Getter;

import java.time.LocalDateTime;

@Getter
public class BoardBumpResponse {

private Long boardId;
private LocalDateTime bumpTime;

public static BoardBumpResponse of(Long boardId, LocalDateTime bumpTime) {
BoardBumpResponse response = new BoardBumpResponse();
response.boardId = boardId;
response.bumpTime = bumpTime;
return response;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import com.gamegoo.gamegoo_v2.content.board.domain.Board;
import com.gamegoo.gamegoo_v2.content.board.dto.request.BoardInsertRequest;
import com.gamegoo.gamegoo_v2.content.board.dto.request.BoardUpdateRequest;
import com.gamegoo.gamegoo_v2.content.board.dto.response.BoardBumpResponse;
import com.gamegoo.gamegoo_v2.content.board.dto.response.BoardByIdResponse;
import com.gamegoo.gamegoo_v2.content.board.dto.response.BoardByIdResponseForMember;
import com.gamegoo.gamegoo_v2.content.board.dto.response.BoardInsertResponse;
Expand Down Expand Up @@ -131,5 +132,16 @@ public MyBoardResponse getMyBoardList(Member member, int pageIdx) {
return MyBoardResponse.of(boardPage);
}

/**
* 게시글 끌올(bump) 기능 (파사드)
* 사용자가 "끌올" 버튼을 누르면 해당 게시글의 bumpTime을 업데이트합니다.
* 단, 마지막 끌올 후 1시간이 지나지 않았다면 예외를 발생시킵니다.
*/

@Transactional
public BoardBumpResponse bumpBoard(Long boardId, Member member) {
Board board = boardService.bumpBoard(boardId, member.getId());
return BoardBumpResponse.of(board.getId(), board.getBumpTime());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.Duration;
import java.time.LocalDateTime;

@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
Expand All @@ -27,6 +30,7 @@ public class BoardService {
private final BoardRepository boardRepository;
public static final int PAGE_SIZE = 20;
public static final int MY_PAGE_SIZE = 10;
private static final Duration BUMP_INTERVAL = Duration.ofMinutes(1);

/**
* 게시글 엔티티 생성 및 저장
Expand Down Expand Up @@ -63,7 +67,7 @@ public Page<Board> findBoards(GameMode gameMode, Tier tier, Position mainP, Mike

public Page<Board> getBoardsWithPagination(GameMode gameMode, Tier tier, Position mainP, Mike mike,
int pageIdx) {
Pageable pageable = PageRequest.of(pageIdx - 1, PAGE_SIZE, Sort.by(Sort.Direction.DESC, "createdAt"));
Pageable pageable = PageRequest.of(pageIdx - 1, PAGE_SIZE, Sort.by(Sort.Direction.DESC, "activityTime"));
return findBoards(gameMode, tier, mainP, mike, pageable);
}

Expand Down Expand Up @@ -136,4 +140,28 @@ public Board saveBoard(Board board) {
return boardRepository.save(board);
}

/**
* 끌올 기능: 사용자가 게시글을 끌올하면 bumpTime을 현재 시간으로 업데이트
*/
@Transactional
public Board bumpBoard(Long boardId, Long memberId) {
Board board = boardRepository.findByIdAndDeleted(boardId, false)
.orElseThrow(() -> new BoardException(ErrorCode.BOARD_NOT_FOUND));

if (!board.getMember().getId().equals(memberId)) {
throw new BoardException(ErrorCode.BUMP_ACCESS_DENIED);
}

LocalDateTime now = LocalDateTime.now();
if (board.getBumpTime() != null) {
Duration diff = Duration.between(board.getBumpTime(), now);
if (diff.compareTo(BUMP_INTERVAL) < 0) {
throw new BoardException(ErrorCode.BUMP_TIME_LIMIT);
}
}

board.bump(now);
return boardRepository.save(board);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,8 @@ public enum ErrorCode {
BOARD_PAGE_BAD_REQUEST(BAD_REQUEST, "BOARD_407", "페이지 값은 0 이상만 가능합니다."),
BOARD_FORBIDDEN_WORD(BAD_REQUEST, "BOARD_408", "금지어가 포함되어 있습니다."),
BOARD_FORBIDDEN_WORD_LOAD_FAILED(INTERNAL_SERVER_ERROR, "BOARD_409", "금지어 파일을 읽어오는데 실패했습니다."),

BUMP_ACCESS_DENIED(FORBIDDEN, "BOARD_410", "게시글 끌어올리기 권한이 없습니다."),
BUMP_TIME_LIMIT(BAD_REQUEST, "BOARD_411", "게시글 끌어올리기는 24시간에 1회만 가능합니다."),
/**
* 매너평가 관련 에러
*/
Expand Down
Loading