-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
303 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
package com.software.ott.friend; | ||
|
||
public enum FriendStatus { | ||
PENDING, ACCEPTED, DECLINED | ||
} |
73 changes: 73 additions & 0 deletions
73
src/main/java/com/software/ott/friend/controller/FriendController.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
package com.software.ott.friend.controller; | ||
|
||
import com.software.ott.common.dto.StringTypeMessageResponse; | ||
import com.software.ott.friend.dto.FriendEmailRequest; | ||
import com.software.ott.friend.dto.FriendRequestResponse; | ||
import com.software.ott.friend.dto.FriendResponse; | ||
import com.software.ott.friend.service.FriendService; | ||
import io.swagger.v3.oas.annotations.Operation; | ||
import io.swagger.v3.oas.annotations.tags.Tag; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.http.HttpStatus; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.web.bind.annotation.*; | ||
|
||
import java.util.List; | ||
|
||
@RestController | ||
@RequiredArgsConstructor | ||
@RequestMapping("/api/friend") | ||
@Tag(name = "친구", description = "친구 관련 API") | ||
public class FriendController { | ||
|
||
private final FriendService friendService; | ||
|
||
@Operation(summary = "친구 요청 보내기", description = "친구의 email을 기반으로 친구요청합니다.") | ||
@PostMapping | ||
public ResponseEntity<StringTypeMessageResponse> sendFriendRequest(@RequestAttribute("memberId") Long memberId, @RequestBody FriendEmailRequest friendEmailRequest) { | ||
friendService.makeFriendRequest(memberId, friendEmailRequest); | ||
return ResponseEntity.status(HttpStatus.CREATED).body(new StringTypeMessageResponse("친구 요청이 생성되었습니다.")); | ||
} | ||
|
||
@Operation(summary = "친구 확인", description = "본인의 친구들을 확인합니다.") | ||
@GetMapping | ||
public ResponseEntity<List<FriendResponse>> getAllFriends(@RequestAttribute("memberId") Long memberId) { | ||
List<FriendResponse> friendResponses = friendService.getAllFriend(memberId); | ||
return ResponseEntity.ok().body(friendResponses); | ||
} | ||
|
||
@Operation(summary = "대기중인 친구 요청들 확인", description = "본인에게 온 친구 요청 대기 목록을 확인합니다.") | ||
@GetMapping("/pending") | ||
public ResponseEntity<List<FriendRequestResponse>> getAllPendingFriendRequest(@RequestAttribute("memberId") Long memberId) { | ||
List<FriendRequestResponse> friendRequestResponses = friendService.getAllFriendRequests(memberId); | ||
return ResponseEntity.ok().body(friendRequestResponses); | ||
} | ||
|
||
@Operation(summary = "거절한 친구 요청들 확인", description = "본인에게 온 친구 요청 중 거절한 요청 목록을 확인합니다.") | ||
@GetMapping("/declined") | ||
public ResponseEntity<List<FriendRequestResponse>> getAllDeclinedFriendRequest(@RequestAttribute("memberId") Long memberId) { | ||
List<FriendRequestResponse> friendRequestResponses = friendService.getAllDeclinedFriends(memberId); | ||
return ResponseEntity.ok().body(friendRequestResponses); | ||
} | ||
|
||
@Operation(summary = "친구 요청 수락", description = "친구 요청을 수락합니다.") | ||
@PutMapping("/accept/{friendRequestId}") | ||
public ResponseEntity<StringTypeMessageResponse> acceptFriendRequest(@RequestAttribute("memberId") Long memberId, @PathVariable Long friendRequestId) { | ||
friendService.acceptFriendRequest(memberId, friendRequestId); | ||
return ResponseEntity.ok().body(new StringTypeMessageResponse("친구 요청이 수락되었습니다.")); | ||
} | ||
|
||
@Operation(summary = "친구 요청 거절", description = "친구 요청을 거절합니다.") | ||
@PutMapping("/decline/{friendRequestId}") | ||
public ResponseEntity<StringTypeMessageResponse> declineFriendRequest(@RequestAttribute("memberId") Long memberId, @PathVariable Long friendRequestId) { | ||
friendService.declineFriendRequest(memberId, friendRequestId); | ||
return ResponseEntity.ok().body(new StringTypeMessageResponse("친구 요청이 거절되었습니다.")); | ||
} | ||
|
||
@Operation(summary = "친구 또는 친구요청 삭제", description = "친구를 삭제합니다.") | ||
@DeleteMapping("/{friendRequestId}") | ||
public ResponseEntity<StringTypeMessageResponse> deleteFriend(@RequestAttribute("memberId") Long memberId, @PathVariable Long friendRequestId) { | ||
friendService.deleteFriend(memberId, friendRequestId); | ||
return ResponseEntity.ok().body(new StringTypeMessageResponse("친구가 삭제되었습니다.")); | ||
} | ||
} |
6 changes: 6 additions & 0 deletions
6
src/main/java/com/software/ott/friend/dto/FriendEmailRequest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
package com.software.ott.friend.dto; | ||
|
||
public record FriendEmailRequest( | ||
String email | ||
) { | ||
} |
10 changes: 10 additions & 0 deletions
10
src/main/java/com/software/ott/friend/dto/FriendRequestResponse.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package com.software.ott.friend.dto; | ||
|
||
public record FriendRequestResponse( | ||
Long friendRequestId, | ||
String requesterName, | ||
String requesterEmail, | ||
String accepterName, | ||
String accepterEmail | ||
) { | ||
} |
8 changes: 8 additions & 0 deletions
8
src/main/java/com/software/ott/friend/dto/FriendResponse.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package com.software.ott.friend.dto; | ||
|
||
public record FriendResponse( | ||
Long friendRequestId, | ||
String friendName, | ||
String friendEmail | ||
) { | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
package com.software.ott.friend.entity; | ||
|
||
import com.software.ott.common.exception.BadRequestException; | ||
import com.software.ott.friend.FriendStatus; | ||
import com.software.ott.member.entity.Member; | ||
import jakarta.persistence.*; | ||
import lombok.*; | ||
|
||
@Builder | ||
@Getter | ||
@Setter | ||
@Entity | ||
@NoArgsConstructor | ||
@AllArgsConstructor | ||
public class Friend { | ||
|
||
@Id | ||
@GeneratedValue(strategy = GenerationType.AUTO) | ||
private Long id; | ||
@ManyToOne | ||
@JoinColumn(name = "requester_id") | ||
private Member requester; | ||
@ManyToOne | ||
@JoinColumn(name = "accepter_id") | ||
private Member accepter; | ||
@Enumerated(EnumType.STRING) | ||
private FriendStatus status; | ||
|
||
public boolean checkMemberIsNotAccepter(Member member) { | ||
return !this.accepter.equals(member); | ||
} | ||
|
||
public boolean checkMemberIsNotRequester(Member member) { | ||
return !this.requester.equals(member); | ||
} | ||
|
||
public void acceptFriendRequest() { | ||
if (!this.status.equals(FriendStatus.PENDING)) { | ||
throw new BadRequestException("대기중인 친구 요청이 아닙니다."); | ||
} | ||
this.status = FriendStatus.ACCEPTED; | ||
} | ||
|
||
public void declinedFriendRequest() { | ||
if (!this.status.equals(FriendStatus.PENDING)) { | ||
throw new BadRequestException("대기중인 친구 요청이 아닙니다."); | ||
} | ||
this.status = FriendStatus.DECLINED; | ||
} | ||
} |
15 changes: 15 additions & 0 deletions
15
src/main/java/com/software/ott/friend/repository/FriendRepository.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package com.software.ott.friend.repository; | ||
|
||
import com.software.ott.friend.FriendStatus; | ||
import com.software.ott.friend.entity.Friend; | ||
import org.springframework.data.jpa.repository.JpaRepository; | ||
import org.springframework.stereotype.Repository; | ||
|
||
import java.util.List; | ||
|
||
@Repository | ||
public interface FriendRepository extends JpaRepository<Friend, Long> { | ||
List<Friend> findAllByAccepterIdAndStatusOrRequesterIdAndStatus(Long accepterId, FriendStatus status1, Long requesterId, FriendStatus status2); | ||
|
||
boolean existsByRequesterIdOrAccepterId(Long requesterId, Long accepterId); | ||
} |
136 changes: 136 additions & 0 deletions
136
src/main/java/com/software/ott/friend/service/FriendService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
package com.software.ott.friend.service; | ||
|
||
import com.software.ott.common.exception.BadRequestException; | ||
import com.software.ott.common.exception.NotFoundException; | ||
import com.software.ott.friend.FriendStatus; | ||
import com.software.ott.friend.dto.FriendEmailRequest; | ||
import com.software.ott.friend.dto.FriendRequestResponse; | ||
import com.software.ott.friend.dto.FriendResponse; | ||
import com.software.ott.friend.entity.Friend; | ||
import com.software.ott.friend.repository.FriendRepository; | ||
import com.software.ott.member.entity.Member; | ||
import com.software.ott.member.repository.MemberRepository; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.stereotype.Service; | ||
import org.springframework.transaction.annotation.Transactional; | ||
|
||
import java.util.List; | ||
import java.util.stream.Collectors; | ||
|
||
@Service | ||
@RequiredArgsConstructor | ||
public class FriendService { | ||
|
||
private final FriendRepository friendRepository; | ||
private final MemberRepository memberRepository; | ||
|
||
@Transactional | ||
public void makeFriendRequest(Long memberId, FriendEmailRequest friendEmailRequest) { | ||
Member requesterMember = memberRepository.findById(memberId) | ||
.orElseThrow(() -> new NotFoundException("id에 해당하는 멤버가 없습니다.")); | ||
Member accepterMember = memberRepository.findByEmail(friendEmailRequest.email()) | ||
.orElseThrow(() -> new NotFoundException("email에 해당하는 멤버가 없습니다.")); | ||
|
||
if (friendRepository.existsByRequesterIdOrAccepterId(memberId, memberId)) { | ||
throw new BadRequestException("이미 친구이거나, 친구요청이 존재합니다."); | ||
} | ||
|
||
friendRepository.save(Friend.builder() | ||
.requester(requesterMember) | ||
.accepter(accepterMember) | ||
.status(FriendStatus.PENDING) | ||
.build()); | ||
} | ||
|
||
@Transactional(readOnly = true) | ||
public List<FriendResponse> getAllFriend(Long memberId) { | ||
return friendRepository.findAllByAccepterIdAndStatusOrRequesterIdAndStatus(memberId, FriendStatus.ACCEPTED, memberId, FriendStatus.ACCEPTED) | ||
.stream().map(friend -> { | ||
if (friend.getRequester().getId().equals(memberId)) { | ||
return new FriendResponse( | ||
friend.getId(), | ||
friend.getAccepter().getName(), | ||
friend.getAccepter().getEmail() | ||
); | ||
} else { | ||
return new FriendResponse( | ||
friend.getId(), | ||
friend.getRequester().getName(), | ||
friend.getRequester().getEmail() | ||
); | ||
} | ||
}) | ||
.collect(Collectors.toList()); | ||
} | ||
|
||
@Transactional(readOnly = true) | ||
public List<FriendRequestResponse> getAllDeclinedFriends(Long memberId) { | ||
return friendRepository.findAllByAccepterIdAndStatusOrRequesterIdAndStatus(memberId, FriendStatus.DECLINED, memberId, FriendStatus.DECLINED) | ||
.stream().map( | ||
Friend -> new FriendRequestResponse( | ||
Friend.getId(), | ||
Friend.getRequester().getName(), | ||
Friend.getRequester().getEmail(), | ||
Friend.getAccepter().getName(), | ||
Friend.getAccepter().getEmail())) | ||
.collect(Collectors.toList()); | ||
} | ||
|
||
@Transactional(readOnly = true) | ||
public List<FriendRequestResponse> getAllFriendRequests(Long memberId) { | ||
return friendRepository.findAllByAccepterIdAndStatusOrRequesterIdAndStatus(memberId, FriendStatus.PENDING, memberId, FriendStatus.PENDING) | ||
.stream().map( | ||
Friend -> new FriendRequestResponse( | ||
Friend.getId(), | ||
Friend.getRequester().getName(), | ||
Friend.getRequester().getEmail(), | ||
Friend.getAccepter().getName(), | ||
Friend.getAccepter().getEmail())) | ||
.collect(Collectors.toList()); | ||
} | ||
|
||
@Transactional | ||
public void acceptFriendRequest(Long memberId, Long friendRequestId) { | ||
Member member = memberRepository.findById(memberId) | ||
.orElseThrow(() -> new NotFoundException("id에 해당하는 멤버가 없습니다.")); | ||
|
||
Friend friendRequest = friendRepository.findById(friendRequestId) | ||
.orElseThrow(() -> new NotFoundException("friendRequestId에 해당하는 친구요청이 없습니다.")); | ||
|
||
if (friendRequest.checkMemberIsNotAccepter(member)) { | ||
throw new BadRequestException("친구 요청을 수락할 권한이 없습니다. 요청받은 사람만 수락할 수 있습니다."); | ||
} | ||
|
||
friendRequest.acceptFriendRequest(); | ||
} | ||
|
||
@Transactional | ||
public void declineFriendRequest(Long memberId, Long friendRequestId) { | ||
Member member = memberRepository.findById(memberId) | ||
.orElseThrow(() -> new NotFoundException("id에 해당하는 멤버가 없습니다.")); | ||
|
||
Friend friendRequest = friendRepository.findById(friendRequestId) | ||
.orElseThrow(() -> new NotFoundException("friendRequestId에 해당하는 친구요청이 없습니다.")); | ||
|
||
if (friendRequest.checkMemberIsNotAccepter(member)) { | ||
throw new BadRequestException("친구 요청을 수락할 권한이 없습니다. 요청받은 사람만 수락할 수 있습니다."); | ||
} | ||
|
||
friendRequest.declinedFriendRequest(); | ||
} | ||
|
||
@Transactional | ||
public void deleteFriend(Long memberId, Long friendRequestId) { | ||
Member member = memberRepository.findById(memberId) | ||
.orElseThrow(() -> new NotFoundException("id에 해당하는 멤버가 없습니다.")); | ||
|
||
Friend friendRequest = friendRepository.findById(friendRequestId) | ||
.orElseThrow(() -> new NotFoundException("friendRequestId에 해당하는 친구요청이 없습니다.")); | ||
|
||
if (friendRequest.checkMemberIsNotRequester(member) && friendRequest.checkMemberIsNotAccepter(member)) { | ||
throw new BadRequestException("친구를 삭제할 권한이 없습니다. 당사자들만 삭제할 수 있습니다."); | ||
} | ||
|
||
friendRepository.deleteById(friendRequestId); | ||
} | ||
} |