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
@@ -1,5 +1,7 @@
package doldol_server.doldol.invite.controller;

import doldol_server.doldol.common.dto.CursorPage;
import doldol_server.doldol.common.request.CursorPageRequest;
import doldol_server.doldol.common.response.ApiResponse;
import doldol_server.doldol.auth.dto.CustomUserDetails;
import doldol_server.doldol.invite.dto.request.InviteCommentCreateRequest;
Expand All @@ -13,11 +15,10 @@
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springdoc.core.annotations.ParameterObject;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@Tag(name = "초대장", description = "파티/모임 초대장 API")
@RestController
@RequestMapping("/invites")
Expand All @@ -38,51 +39,66 @@ public ApiResponse<InviteResponse> createInvite(
return ApiResponse.created(inviteService.createInvite(request, userDetails.getUserId()));
}

@Operation(
summary = "내 초대장 목록 조회",
security = {@SecurityRequirement(name = "jwt")}
)
@GetMapping
public ApiResponse<CursorPage<InviteResponse, Long>> getMyInvites(
@ParameterObject @Valid CursorPageRequest request,
@AuthenticationPrincipal CustomUserDetails userDetails
) {
return ApiResponse.ok(inviteService.getMyInvites(userDetails.getUserId(), request));
}

@Operation(summary = "초대장 상세 조회")
@GetMapping("/{inviteId}")
public ApiResponse<InviteResponse> getInvite(@PathVariable Long inviteId) {
return ApiResponse.ok(inviteService.getInvite(inviteId));
@GetMapping("/{inviteCode}")
public ApiResponse<InviteResponse> getInvite(@PathVariable String inviteCode) {
return ApiResponse.ok(inviteService.getInvite(inviteCode));
}

@Operation(summary = "초대장 댓글 등록")
@PostMapping("/{inviteId}/comments")
@PostMapping("/{inviteCode}/comments")
public ApiResponse<InviteCommentResponse> addComment(
@PathVariable Long inviteId,
@PathVariable String inviteCode,
@Valid @RequestBody InviteCommentCreateRequest request
) {
return ApiResponse.created(inviteService.addComment(inviteId, request));
return ApiResponse.created(inviteService.addComment(inviteCode, request));
}

@Operation(summary = "초대장 댓글 목록 조회")
@GetMapping("/{inviteId}/comments")
public ApiResponse<List<InviteCommentResponse>> getComments(@PathVariable Long inviteId) {
return ApiResponse.ok(inviteService.getComments(inviteId));
@GetMapping("/{inviteCode}/comments")
public ApiResponse<CursorPage<InviteCommentResponse, Long>> getComments(
@PathVariable String inviteCode,
@ParameterObject @Valid CursorPageRequest request
) {
return ApiResponse.ok(inviteService.getComments(inviteCode, request));
}

@Operation(
summary = "초대장 수정",
security = {@SecurityRequirement(name = "jwt")}
)
@PutMapping("/{inviteId}")
@PutMapping("/{inviteCode}")
public ApiResponse<Void> updateInvite(
@PathVariable Long inviteId,
@PathVariable String inviteCode,
@Valid @RequestBody InviteUpdateRequest request,
@AuthenticationPrincipal CustomUserDetails userDetails
) {
inviteService.updateInvite(inviteId, request, userDetails.getUserId());
inviteService.updateInvite(inviteCode, request, userDetails.getUserId());
return ApiResponse.noContent();
}

@Operation(
summary = "초대장 삭제",
security = {@SecurityRequirement(name = "jwt")}
)
@DeleteMapping("/{inviteId}")
@DeleteMapping("/{inviteCode}")
public ApiResponse<Void> deleteInvite(
@PathVariable Long inviteId,
@PathVariable String inviteCode,
@AuthenticationPrincipal CustomUserDetails userDetails
) {
inviteService.deleteInvite(inviteId, userDetails.getUserId());
inviteService.deleteInvite(inviteCode, userDetails.getUserId());
return ApiResponse.noContent();
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
package doldol_server.doldol.invite.repository;

import doldol_server.doldol.invite.entity.InviteComment;
import doldol_server.doldol.invite.repository.custom.InviteCommentRepositoryCustom;
import org.springframework.data.jpa.repository.JpaRepository;

public interface InviteCommentRepository extends JpaRepository<InviteComment, Long> {
public interface InviteCommentRepository extends JpaRepository<InviteComment, Long>, InviteCommentRepositoryCustom {
}

Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
package doldol_server.doldol.invite.repository;

import doldol_server.doldol.invite.entity.Invite;
import doldol_server.doldol.invite.repository.custom.InviteRepositoryCustom;
import org.springframework.data.jpa.repository.EntityGraph;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.Optional;

public interface InviteRepository extends JpaRepository<Invite, Long> {
public interface InviteRepository extends JpaRepository<Invite, Long>, InviteRepositoryCustom {

@EntityGraph(attributePaths = {"comments"})
Optional<Invite> findWithCommentsByInviteId(Long inviteId);
Optional<Invite> findWithCommentsByInviteCode(String inviteCode);

Optional<Invite> findByInviteCode(String inviteCode);
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package doldol_server.doldol.invite.repository.custom;

import doldol_server.doldol.common.request.CursorPageRequest;
import doldol_server.doldol.invite.dto.response.InviteCommentResponse;

import java.util.List;

public interface InviteCommentRepositoryCustom {

List<InviteCommentResponse> findCommentsByInviteCode(String inviteCode, CursorPageRequest request);
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package doldol_server.doldol.invite.repository.custom;

import com.querydsl.core.types.dsl.BooleanExpression;
import com.querydsl.jpa.impl.JPAQueryFactory;
import doldol_server.doldol.common.request.CursorPageRequest;
import doldol_server.doldol.invite.dto.response.InviteCommentResponse;
import doldol_server.doldol.invite.entity.InviteComment;
import doldol_server.doldol.invite.entity.QInvite;
import doldol_server.doldol.invite.entity.QInviteComment;
import lombok.RequiredArgsConstructor;

import java.util.List;

@RequiredArgsConstructor
public class InviteCommentRepositoryCustomImpl implements InviteCommentRepositoryCustom {

private final JPAQueryFactory queryFactory;

@Override
public List<InviteCommentResponse> findCommentsByInviteCode(String inviteCode, CursorPageRequest request) {
QInviteComment comment = QInviteComment.inviteComment;
QInvite invite = QInvite.invite;

BooleanExpression cursorCondition = null;
if (request.cursorId() != null) {
cursorCondition = comment.commentId.lt(request.cursorId());
}

List<InviteComment> comments = queryFactory
.selectFrom(comment)
.join(comment.invite, invite)
.where(
invite.inviteCode.eq(inviteCode),
cursorCondition
)
.orderBy(comment.commentId.desc())
.limit(request.size() + 1L)
.fetch();

return comments.stream()
.map(InviteCommentResponse::from)
.toList();
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package doldol_server.doldol.invite.repository.custom;

import doldol_server.doldol.common.request.CursorPageRequest;
import doldol_server.doldol.invite.dto.response.InviteResponse;

import java.util.List;

public interface InviteRepositoryCustom {

List<InviteResponse> findInvitesByUserId(Long userId, CursorPageRequest request);
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package doldol_server.doldol.invite.repository.custom;

import com.querydsl.core.types.dsl.BooleanExpression;
import com.querydsl.jpa.impl.JPAQueryFactory;
import doldol_server.doldol.common.request.CursorPageRequest;
import doldol_server.doldol.invite.dto.response.InviteResponse;
import doldol_server.doldol.invite.entity.Invite;
import doldol_server.doldol.invite.entity.QInvite;
import lombok.RequiredArgsConstructor;

import java.util.List;

@RequiredArgsConstructor
public class InviteRepositoryCustomImpl implements InviteRepositoryCustom {

private final JPAQueryFactory queryFactory;

@Override
public List<InviteResponse> findInvitesByUserId(Long userId, CursorPageRequest request) {
QInvite invite = QInvite.invite;

BooleanExpression cursorCondition = null;
if (request.cursorId() != null) {
cursorCondition = invite.inviteId.lt(request.cursorId());
}

List<Invite> invites = queryFactory
.selectFrom(invite)
.where(
invite.user.id.eq(userId),
cursorCondition
)
.orderBy(invite.inviteId.desc())
.limit(request.size() + 1L)
.fetch();

return invites.stream()
.map(InviteResponse::from)
.toList();
}
}

Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package doldol_server.doldol.invite.service;

import doldol_server.doldol.common.dto.CursorPage;
import doldol_server.doldol.common.exception.CustomException;
import doldol_server.doldol.common.request.CursorPageRequest;
import doldol_server.doldol.invite.dto.request.InviteCommentCreateRequest;
import doldol_server.doldol.invite.dto.request.InviteCreateRequest;
import doldol_server.doldol.invite.dto.request.InviteUpdateRequest;
Expand Down Expand Up @@ -52,15 +54,15 @@ public InviteResponse createInvite(InviteCreateRequest request, Long userId) {
}

@Transactional(readOnly = true)
public InviteResponse getInvite(Long inviteId) {
Invite invite = inviteRepository.findWithCommentsByInviteId(inviteId)
public InviteResponse getInvite(String inviteCode) {
Invite invite = inviteRepository.findWithCommentsByInviteCode(inviteCode)
.orElseThrow(() -> new CustomException(InviteErrorCode.INVITE_NOT_FOUND));
return InviteResponse.from(invite);
}

@Transactional
public InviteCommentResponse addComment(Long inviteId, InviteCommentCreateRequest request) {
Invite invite = inviteRepository.findById(inviteId)
public InviteCommentResponse addComment(String inviteCode, InviteCommentCreateRequest request) {
Invite invite = inviteRepository.findByInviteCode(inviteCode)
.orElseThrow(() -> new CustomException(InviteErrorCode.INVITE_NOT_FOUND));

InviteComment comment = InviteComment.builder()
Expand All @@ -74,18 +76,18 @@ public InviteCommentResponse addComment(Long inviteId, InviteCommentCreateReques
}

@Transactional(readOnly = true)
public List<InviteCommentResponse> getComments(Long inviteId) {
Invite invite = inviteRepository.findWithCommentsByInviteId(inviteId)
public CursorPage<InviteCommentResponse, Long> getComments(String inviteCode, CursorPageRequest request) {
// 초대장 존재 여부 확인
inviteRepository.findByInviteCode(inviteCode)
.orElseThrow(() -> new CustomException(InviteErrorCode.INVITE_NOT_FOUND));
return invite.getComments()
.stream()
.map(InviteCommentResponse::from)
.toList();

List<InviteCommentResponse> comments = inviteCommentRepository.findCommentsByInviteCode(inviteCode, request);
return CursorPage.of(comments, request.size(), InviteCommentResponse::getCommentId);
}

@Transactional
public void updateInvite(Long inviteId, InviteUpdateRequest request, Long userId) {
Invite invite = inviteRepository.findById(inviteId)
public void updateInvite(String inviteCode, InviteUpdateRequest request, Long userId) {
Invite invite = inviteRepository.findByInviteCode(inviteCode)
.orElseThrow(() -> new CustomException(InviteErrorCode.INVITE_NOT_FOUND));

if (!invite.getUser().getId().equals(userId)) {
Expand All @@ -105,8 +107,8 @@ public void updateInvite(Long inviteId, InviteUpdateRequest request, Long userId
}

@Transactional
public void deleteInvite(Long inviteId, Long userId) {
Invite invite = inviteRepository.findById(inviteId)
public void deleteInvite(String inviteCode, Long userId) {
Invite invite = inviteRepository.findByInviteCode(inviteCode)
.orElseThrow(() -> new CustomException(InviteErrorCode.INVITE_NOT_FOUND));

if (!invite.getUser().getId().equals(userId)) {
Expand All @@ -115,5 +117,11 @@ public void deleteInvite(Long inviteId, Long userId) {

inviteRepository.delete(invite);
}

@Transactional(readOnly = true)
public CursorPage<InviteResponse, Long> getMyInvites(Long userId, CursorPageRequest request) {
List<InviteResponse> invites = inviteRepository.findInvitesByUserId(userId, request);
return CursorPage.of(invites, request.size(), InviteResponse::getInviteId);
}
}

Loading