Skip to content

Commit

Permalink
Merge pull request #124 from Media-XI/ARTDEV-139-be-팔로우-팔로잉-목록-확인
Browse files Browse the repository at this point in the history
feat: Artdev 139 be 팔로우 팔로잉 목록 확인
  • Loading branch information
haroya01 authored Feb 6, 2024
2 parents e6aa015 + d574751 commit c10a304
Show file tree
Hide file tree
Showing 10 changed files with 326 additions and 14 deletions.
Original file line number Diff line number Diff line change
@@ -1,17 +1,22 @@
package com.example.codebase.controller;

import com.example.codebase.domain.follow.dto.FollowMembersResponseDTO;
import com.example.codebase.domain.follow.service.FollowService;
import com.example.codebase.exception.LoginRequiredException;
import com.example.codebase.util.SecurityUtil;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.constraints.PositiveOrZero;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.Optional;

@RestController
@Tag(name = "Follow", description = "팔로우 관련 API")
@Validated
Expand Down Expand Up @@ -45,4 +50,31 @@ public ResponseEntity unfollowMember(@PathVariable("username") String followUser
return new ResponseEntity("언팔로잉 했습니다.", HttpStatus.NO_CONTENT);
}


@Operation(summary = "팔로잉", description = "해당 유저가 팔로잉 하는 사람 목록을 조회 합니다")
@GetMapping("/{username}/following")
public ResponseEntity getFollowingList(@PathVariable("username") String username,
@PositiveOrZero @RequestParam(defaultValue = "0") int page,
@PositiveOrZero @RequestParam(defaultValue = "10") int size) {
Optional<String> loginUsername = SecurityUtil.getCurrentUsername();
PageRequest pageRequest = PageRequest.of(page, size);
FollowMembersResponseDTO followingListResponse = followService.getFollowingList(loginUsername, username, pageRequest);

return new ResponseEntity(followingListResponse, HttpStatus.OK);
}


@Operation(summary = "팔로워", description = "해당 유저를 팔로워 하는 사람 목록을 조회 합니다")
@GetMapping("{username}/follower")
public ResponseEntity getFollowerList(@PathVariable("username") String username,
@PositiveOrZero @RequestParam(defaultValue = "0") int page,
@PositiveOrZero @RequestParam(defaultValue = "10") int size) {
Optional<String> loginUsername = SecurityUtil.getCurrentUsername();
PageRequest pageRequest = PageRequest.of(page, size);
FollowMembersResponseDTO followingListResponse = followService.getFollowerList(loginUsername, username, pageRequest);

return new ResponseEntity(followingListResponse, HttpStatus.OK);
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.example.codebase.domain.follow.dto;

import com.example.codebase.domain.member.entity.Member;
import com.example.codebase.domain.member.entity.RoleStatus;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
@AllArgsConstructor
@Builder
public class FollowMemberDetailResponseDTO {

private String userId;
private String username;
private String profileImage;
private String introduction;
private RoleStatus roleStatus;
private String status;

public static FollowMemberDetailResponseDTO of(Member member, String status){
return FollowMemberDetailResponseDTO.builder()
.userId(member.getId().toString())
.username(member.getUsername())
.profileImage(member.getPicture())
.introduction(member.getIntroduction())
.roleStatus(member.getRoleStatus())
.status(status)
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.example.codebase.domain.follow.dto;

import com.example.codebase.controller.dto.PageInfo;
import lombok.*;

import java.util.List;

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class FollowMembersResponseDTO {

private List<FollowMemberDetailResponseDTO> followingList;

private PageInfo pageInfo;

public static FollowMembersResponseDTO of(List<FollowMemberDetailResponseDTO> followMemberDetailResponseDTO, PageInfo pageInfo ) {
return FollowMembersResponseDTO.builder()
.followingList(followMemberDetailResponseDTO)
.pageInfo(pageInfo)
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,28 +18,29 @@ public class Follow implements Persistable<FollowIds>{

@Id
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "follow_id", columnDefinition = "BINARY(16)")
private Member follow;
@JoinColumn(name = "follower_id", columnDefinition = "BINARY(16)")
private Member follower;

@Id
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "follower_id", columnDefinition = "BINARY(16)")
private Member follower;
@JoinColumn(name = "following_id", columnDefinition = "BINARY(16)")
private Member following;


@Column(name = "follow_time")
@Builder.Default
private LocalDateTime followTime = null;

public static Follow of(Member follow, Member follower) {
public static Follow of(Member follower, Member following) {
return Follow.builder()
.follow(follow)
.follower(follower)
.following(following)
.build();
}

@Override
public FollowIds getId() {
return new FollowIds(this.follow.getId(), this.follower.getId());
return new FollowIds(this.follower.getId(), this.following.getId());
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,17 @@
@AllArgsConstructor
public class FollowIds implements Serializable {

private UUID follow;

private UUID follower;

public static FollowIds of(Member follow, Member follower) {
return new FollowIds(follow.getId(), follower.getId());
private UUID following;


public static FollowIds of(Member follower, Member following) {
return new FollowIds(follower.getId(), following.getId());
}

public void valid() {
if (follow == follower) {
if (follower == following) {
throw new RuntimeException("자신을 팔로우 할 수 없습니다.");
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.example.codebase.domain.follow.entity;

public interface FollowWithIsFollow {

Follow getFollow();

String getStatus();
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,36 @@

import com.example.codebase.domain.follow.entity.Follow;
import com.example.codebase.domain.follow.entity.FollowIds;
import com.example.codebase.domain.follow.entity.FollowWithIsFollow;
import com.example.codebase.domain.member.entity.Member;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;

public interface FollowRepository extends JpaRepository<Follow, FollowIds> {
}


@Query("SELECT f AS follow, " +
"CASE WHEN f.following = :loginMember THEN 'self' " +
"WHEN f2.follower = :loginMember THEN 'follow' ELSE 'none' END as status " +
"FROM Follow f LEFT JOIN Follow f2 ON f.following = f2.following " +
"AND f2.follower = :loginMember " +
"WHERE f.follower = :targetMember " +
"ORDER BY CASE WHEN f.following = :loginMember THEN 1 " +
"WHEN f2.follower = :loginMember THEN 2 ELSE 3 END, " +
"f.followTime ASC")
Page<FollowWithIsFollow> findFollowingByTargetMember(Member targetMember, Member loginMember, PageRequest pageRequest);


@Query("SELECT f AS follow, " +
"CASE WHEN f.follower = :loginMember THEN 'self' " +
"WHEN f2.follower = :loginMember THEN 'follow' ELSE 'none' END as status " +
"FROM Follow f LEFT JOIN Follow f2 ON f.follower = f2.following " +
"AND f2.follower = :loginMember " +
"WHERE f.following = :targetMember " +
"ORDER BY CASE WHEN f.follower = :loginMember THEN 1 " +
"WHEN f2.follower = :loginMember THEN 2 ELSE 3 END, " +
"f.followTime ASC")
Page<FollowWithIsFollow> findFollowerByTargetMember(Member targetMember, Member loginMember, PageRequest pageRequest);
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,22 @@
package com.example.codebase.domain.follow.service;

import com.example.codebase.controller.dto.PageInfo;
import com.example.codebase.domain.follow.dto.FollowMemberDetailResponseDTO;
import com.example.codebase.domain.follow.dto.FollowMembersResponseDTO;
import com.example.codebase.domain.follow.entity.Follow;
import com.example.codebase.domain.follow.entity.FollowIds;
import com.example.codebase.domain.follow.entity.FollowWithIsFollow;
import com.example.codebase.domain.follow.repository.FollowRepository;
import com.example.codebase.domain.member.entity.Member;
import com.example.codebase.domain.member.exception.NotFoundMemberException;
import com.example.codebase.domain.member.repository.MemberRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Optional;

@Service
Expand Down Expand Up @@ -55,4 +63,40 @@ public void unfollowMember(String username, String followUser) {
throw new RuntimeException("팔로잉 중이 아닙니다.");
}
}

@Transactional(readOnly = true)
public FollowMembersResponseDTO getFollowingList(Optional<String> loginUsername, String targetUsername, PageRequest pageRequest) {

Check warning on line 68 in src/main/java/com/example/codebase/domain/follow/service/FollowService.java

View workflow job for this annotation

GitHub Actions / Qodana Community for JVM

'Optional' used as field or parameter type

`Optional` used as type for parameter 'loginUsername'
Member targetMember = memberRepository.findByUsername(targetUsername).orElseThrow(NotFoundMemberException::new);
Member loginMember = loginUsername.map(s -> memberRepository.findByUsername(s)
.orElseThrow(NotFoundMemberException::new))
.orElse(null);

Page<FollowWithIsFollow> followingList = followRepository.findFollowingByTargetMember(targetMember, loginMember, pageRequest);
PageInfo pageInfo = PageInfo.from(followingList);

List<FollowMemberDetailResponseDTO> followingMemberResponses = followingList.getContent().stream()
.map(followWithIsFollow ->
FollowMemberDetailResponseDTO.of(followWithIsFollow.getFollow().getFollowing(), followWithIsFollow.getStatus()))
.toList();

return FollowMembersResponseDTO.of(followingMemberResponses, pageInfo);
}

@Transactional(readOnly = true)
public FollowMembersResponseDTO getFollowerList(Optional<String> loginUsername, String targetUsername, PageRequest pageRequest) {

Check warning on line 86 in src/main/java/com/example/codebase/domain/follow/service/FollowService.java

View workflow job for this annotation

GitHub Actions / Qodana Community for JVM

'Optional' used as field or parameter type

`Optional` used as type for parameter 'loginUsername'
Member targetMember = memberRepository.findByUsername(targetUsername).orElseThrow(NotFoundMemberException::new);
Member loginMember = loginUsername.map(s -> memberRepository.findByUsername(s)
.orElseThrow(NotFoundMemberException::new))
.orElse(null);

Page<FollowWithIsFollow> followerList = followRepository.findFollowerByTargetMember(targetMember, loginMember, pageRequest);
PageInfo pageInfo = PageInfo.from(followerList);

List<FollowMemberDetailResponseDTO> followerMemberResponses = followerList.getContent().stream()
.map(followWithIsFollow ->
FollowMemberDetailResponseDTO.of(followWithIsFollow.getFollow().getFollower(), followWithIsFollow.getStatus()))
.toList();

return FollowMembersResponseDTO.of(followerMemberResponses, pageInfo);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
ALTER TABLE `follow`
CHANGE COLUMN `follower_id` `following_id` BINARY(16) NOT NULL ,
CHANGE COLUMN `follow_id` `follower_id` BINARY(16) NOT NULL ;
Loading

0 comments on commit c10a304

Please sign in to comment.