Skip to content

Commit

Permalink
Merge branch 'develop' into feature/#36/TIL
Browse files Browse the repository at this point in the history
  • Loading branch information
junseokkim authored Feb 4, 2024
2 parents 5d090ca + 822f682 commit 3533f79
Show file tree
Hide file tree
Showing 27 changed files with 806 additions and 164 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package com.umc.networkingService.domain.friend.controller;

import com.umc.networkingService.config.security.auth.CurrentMember;
import com.umc.networkingService.domain.friend.dto.response.FriendIdResponse;
import com.umc.networkingService.domain.friend.dto.response.FriendInquiryByStatusResponse;
import com.umc.networkingService.domain.friend.service.FriendService;
import com.umc.networkingService.domain.member.entity.Member;
import com.umc.networkingService.global.common.base.BaseResponse;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
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.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.web.PageableDefault;
import org.springframework.security.core.parameters.P;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.UUID;

@Tag(name = "์นœ๊ตฌ API", description = "์นœ๊ตฌ ๊ด€๋ จ API")
@RestController
@RequiredArgsConstructor
@RequestMapping("/friends")
public class FriendController {

private final FriendService friendService;

@Operation(summary = "์นœ๊ตฌ ์ถ”๊ฐ€ API", description = "์ƒˆ๋กœ์šด ์นœ๊ตฌ๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” API์ž…๋‹ˆ๋‹ค.")
@ApiResponses(value = {
@ApiResponse(responseCode = "COMMON200", description = "์„ฑ๊ณต"),
@ApiResponse(responseCode = "MEMBER001", description = "์กด์žฌํ•˜์ง€ ์•Š๋Š” ๋ฉค๋ฒ„๋ฅผ ์นœ๊ตฌ ์ถ”๊ฐ€ํ•œ ๊ฒฝ์šฐ ๋ฐœ์ƒ"),
@ApiResponse(responseCode = "FRIEND001", description = "์ด๋ฏธ ์นœ๊ตฌ ๊ด€๊ณ„์ผ ๊ฒฝ์šฐ ๋ฐœ์ƒ")
})
@Parameter(name = "memberId", in = ParameterIn.PATH, required = true, description = "์นœ๊ตฌ ์ถ”๊ฐ€ํ•  ๋ฉค๋ฒ„ id์ž…๋‹ˆ๋‹ค.")
@PostMapping("/{memberId}")
public BaseResponse<FriendIdResponse> createNewFriend(@CurrentMember Member member,
@PathVariable UUID memberId) {
return BaseResponse.onSuccess(friendService.createNewFriend(member, memberId));
}

@Operation(summary = "์นœ๊ตฌ ์‚ญ์ œ API", description = "์นœ๊ตฌ ๊ด€๊ณ„๋ฅผ ์‚ญ์ œํ•˜๋Š” API์ž…๋‹ˆ๋‹ค.")
@ApiResponses(value = {
@ApiResponse(responseCode = "COMMON200", description = "์„ฑ๊ณต"),
@ApiResponse(responseCode = "MEMBER001", description = "์กด์žฌํ•˜์ง€ ์•Š๋Š” ๋ฉค๋ฒ„๋ฅผ ์นœ๊ตฌ ์‚ญ์ œํ•œ ๊ฒฝ์šฐ ๋ฐœ์ƒ"),
@ApiResponse(responseCode = "FRIEND002", description = "์นœ๊ตฌ ๊ด€๊ณ„๊ฐ€ ์•„๋‹Œ๋ฐ ์‚ญ์ œํ•œ ๊ฒฝ์šฐ ๋ฐœ์ƒ")
})
@Parameter(name = "memberId", in = ParameterIn.PATH, required = true, description = "์นœ๊ตฌ ์‚ญ์ œํ•  ๋ฉค๋ฒ„ id์ž…๋‹ˆ๋‹ค.")
@DeleteMapping("/{memberId}")
public BaseResponse<FriendIdResponse> deleteFriend(@CurrentMember Member member,
@PathVariable UUID memberId) {
return BaseResponse.onSuccess(friendService.deleteFriend(member, memberId));
}

@Operation(summary = "์ ‘์†/๋น„์ ‘์† ์ค‘์ธ ์นœ๊ตฌ ๋ชฉ๋ก ์กฐํšŒ API", description = "์นœ๊ตฌ ๊ด€๊ณ„์ธ ๋ฉค๋ฒ„ ์ค‘ ์ ‘์† ๋˜๋Š” ๋น„์ ‘์† ์ค‘์ธ ๋ฉค๋ฒ„ ์กฐํšŒ API์ž…๋‹ˆ๋‹ค.")
@ApiResponses(value = {
@ApiResponse(responseCode = "COMMON200", description = "์„ฑ๊ณต")
})
@Parameters(value = {
@Parameter(name = "status", required = true, description = "์ ‘์† ์ƒํƒœ์ž…๋‹ˆ๋‹ค."),
@Parameter(name = "pageable", hidden = true),
@Parameter(name = "size", required = true, description = "ํ•œ ํŽ˜์ด์ง€์— ํฌํ•จ๋˜๋Š” ๋ชฉ๋ก ๊ฐœ์ˆ˜์ž…๋‹ˆ๋‹ค.")
})
@GetMapping
public BaseResponse<FriendInquiryByStatusResponse> inquiryFriendsByStatus(
@CurrentMember Member member,
@RequestParam boolean status,
@PageableDefault(page = 1, sort = "receiver.nickname", direction = Sort.Direction.ASC) Pageable pageable) {
return BaseResponse.onSuccess(friendService.inquiryFriendsByStatus(member, status, pageable));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.umc.networkingService.domain.friend.dto.response;

import lombok.AllArgsConstructor;
import lombok.Getter;

import java.util.UUID;

@Getter
@AllArgsConstructor
public class FriendIdResponse {
private UUID friendId;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.umc.networkingService.domain.friend.dto.response;

import com.umc.networkingService.domain.member.dto.SemesterPartInfo;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.util.List;
import java.util.UUID;

@Getter
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class FriendInquiryByStatusResponse {
private List<FriendInfo> friends;
private boolean hasNext;

@Getter
@Builder
@AllArgsConstructor
@NoArgsConstructor
public static class FriendInfo {
private UUID memberId;
private String nickname;
private String name;
private String profileImage;
private String universityName;
private List<String> campusPositions;
private List<String> centerPositions;
private List<SemesterPartInfo> semesterParts;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.umc.networkingService.domain.friend.mapper;

import com.umc.networkingService.domain.friend.dto.response.FriendInquiryByStatusResponse;
import com.umc.networkingService.domain.friend.entity.Friend;
import com.umc.networkingService.domain.member.dto.SemesterPartInfo;
import com.umc.networkingService.domain.member.entity.Member;
import org.springframework.stereotype.Component;

import java.util.List;

@Component
public class FriendMapper {

public Friend toFriend(Member sender, Member receiver) {
return Friend.builder()
.sender(sender)
.receiver(receiver)
.build();
}

public FriendInquiryByStatusResponse.FriendInfo toFriendInfo(Member member,
List<String> campusPositions,
List<String> centerPositions,
List<SemesterPartInfo> semesterParts) {
return FriendInquiryByStatusResponse.FriendInfo.builder()
.memberId(member.getId())
.nickname(member.getNickname())
.name(member.getName())
.profileImage(member.getProfileImage())
.universityName(member.getUniversity().getName())
.campusPositions(campusPositions)
.centerPositions(centerPositions)
.semesterParts(semesterParts)
.build();

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,25 @@

import com.umc.networkingService.domain.friend.entity.Friend;
import com.umc.networkingService.domain.member.entity.Member;
import io.lettuce.core.dynamic.annotation.Param;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;

import java.time.LocalDateTime;
import java.util.Optional;
import java.util.UUID;

public interface FriendRepository extends JpaRepository<Friend, UUID> {
Optional<Friend> findBySenderAndReceiver(Member sender, Member receiver);
boolean existsBySenderAndReceiver(Member sender, Member receiver);

@Query("SELECT f.receiver FROM Friend f WHERE f.sender = :member AND " +
"(:status = true AND f.receiver.lastActiveTime >= :fiveMinutesAgo OR " +
":status = false AND f.receiver.lastActiveTime < :fiveMinutesAgo)")
Page<Member> findFriendsByStatus(@Param("member") Member member,
@Param("status") boolean status,
@Param("fiveMinutesAgo") LocalDateTime fiveMinutesAgo,
Pageable pageable);
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
package com.umc.networkingService.domain.friend.service;

import com.umc.networkingService.domain.friend.dto.response.FriendIdResponse;
import com.umc.networkingService.domain.friend.dto.response.FriendInquiryByStatusResponse;
import com.umc.networkingService.domain.member.entity.Member;
import org.springframework.data.domain.Pageable;

import java.util.UUID;

public interface FriendService {
FriendIdResponse createNewFriend(Member member, UUID memberId);
FriendIdResponse deleteFriend(Member member, UUID memberId);
FriendInquiryByStatusResponse inquiryFriendsByStatus(Member member, boolean status, Pageable pageable);
boolean checkFriend(Member sender, Member receiver);
}
Original file line number Diff line number Diff line change
@@ -1,18 +1,91 @@
package com.umc.networkingService.domain.friend.service;

import com.umc.networkingService.domain.friend.dto.response.FriendIdResponse;
import com.umc.networkingService.domain.friend.dto.response.FriendInquiryByStatusResponse;
import com.umc.networkingService.domain.friend.entity.Friend;
import com.umc.networkingService.domain.friend.mapper.FriendMapper;
import com.umc.networkingService.domain.friend.repository.FriendRepository;
import com.umc.networkingService.domain.member.entity.Member;
import com.umc.networkingService.domain.member.entity.PositionType;
import com.umc.networkingService.domain.member.mapper.MemberMapper;
import com.umc.networkingService.domain.member.service.MemberService;
import com.umc.networkingService.global.common.exception.ErrorCode;
import com.umc.networkingService.global.common.exception.RestApiException;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

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

@Service
@RequiredArgsConstructor
public class FriendServiceImpl implements FriendService {

private final FriendRepository friendRepository;
private final FriendMapper friendMapper;
private final MemberMapper memberMapper;

private final MemberService memberService;

// ์นœ๊ตฌ ์ถ”๊ฐ€ ํ•จ์ˆ˜
@Override
public FriendIdResponse createNewFriend(Member member, UUID memberId) {
Member loginMember = memberService.loadEntity(member.getId());

Member friendMember = memberService.loadEntity(memberId);

if (friendRepository.existsBySenderAndReceiver(loginMember, friendMember))
throw new RestApiException(ErrorCode.ALREADY_FRIEND_RELATION);

return createAndSaveNewFriend(loginMember, friendMember);
}

// ์นœ๊ตฌ ์‚ญ์ œ ํ•จ์ˆ˜
@Override
public FriendIdResponse deleteFriend(Member member, UUID memberId) {
Member loginMember = memberService.loadEntity(member.getId());

Member friendMember = memberService.loadEntity(memberId);

// ์กด์žฌํ•˜์ง€ ์•Š์„ ๊ฒฝ์šฐ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ
Friend friend = friendRepository.findBySenderAndReceiver(loginMember, friendMember)
.orElseThrow(() -> new RestApiException(ErrorCode.NOT_FRIEND_RELATION));

friend.delete();

return new FriendIdResponse(friend.getId());
}

@Override
public FriendInquiryByStatusResponse inquiryFriendsByStatus(Member member, boolean status, Pageable pageable) {
LocalDateTime fiveMinutesAgo = LocalDateTime.now().minusMinutes(5);
Page<Member> friends = friendRepository.findFriendsByStatus(member, status, fiveMinutesAgo, pageable);

List<FriendInquiryByStatusResponse.FriendInfo> friendInfos = friends.stream()
.map(friend -> friendMapper.toFriendInfo(
friend,
memberService.getPositionNamesByType(friend, PositionType.CAMPUS),
memberService.getPositionNamesByType(friend, PositionType.CENTER),
memberMapper.toSemesterPartInfos(friend.getSemesterParts())
)).toList();


return new FriendInquiryByStatusResponse(friendInfos, friends.hasNext());
}

// ์นœ๊ตฌ ์—ฌ๋ถ€ ํ™•์ธ ํ•จ์ˆ˜
@Override
public boolean checkFriend(Member sender, Member receiver) {
return friendRepository.existsBySenderAndReceiver(sender, receiver);
}

private FriendIdResponse createAndSaveNewFriend(Member loginMember, Member friendMember) {
Friend friend = friendMapper.toFriend(loginMember, friendMember);
UUID savedFriendId = friendRepository.save(friend).getId();

return new FriendIdResponse(savedFriendId);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.umc.networkingService.domain.friend.service;


import com.umc.networkingService.domain.member.dto.response.MemberInquiryProfileResponse;
import com.umc.networkingService.domain.member.entity.Member;

import java.util.UUID;

public interface FriendShipService {
MemberInquiryProfileResponse inquiryProfile(Member member, UUID memberId);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package com.umc.networkingService.domain.friend.service;

import com.umc.networkingService.domain.friend.repository.FriendRepository;
import com.umc.networkingService.domain.member.dto.response.MemberInquiryProfileResponse;
import com.umc.networkingService.domain.member.entity.Member;
import com.umc.networkingService.domain.member.entity.MemberRelation;
import com.umc.networkingService.domain.member.mapper.MemberMapper;
import com.umc.networkingService.domain.member.repository.MemberRepository;
import com.umc.networkingService.domain.member.service.MemberService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.UUID;

@Service
@RequiredArgsConstructor
public class FriendShipServiceImpl implements FriendShipService{
private final FriendService friendService;
private final MemberService memberService;

private final MemberMapper memberMapper;

// ํ”„๋กœํ•„ ์กฐํšŒ ํ•จ์ˆ˜
@Override
public MemberInquiryProfileResponse inquiryProfile(Member member, UUID memberId) {

Member loginMember = memberService.loadEntity(member.getId());
// ๋ณธ์ธ ํ”„๋กœํ•„ ์กฐํšŒ์ธ ๊ฒฝ์šฐ
if (memberId == null || loginMember.getId().equals(memberId)) {
return memberMapper.toInquiryProfileResponse(loginMember, MemberRelation.MINE);
}

Member inquiryMember = memberService.loadEntity(memberId);

// ์นœ๊ตฌ ํ”„๋กœํ•„ ์กฐํšŒ์ธ ๊ฒฝ์šฐ
if (friendService.checkFriend(loginMember, inquiryMember)) {
return memberMapper.toInquiryProfileResponse(inquiryMember, MemberRelation.FRIEND);
}

// ์ด์™ธ์˜ ํ”„๋กœํ•„ ์กฐํšŒ์ธ ๊ฒฝ์šฐ
return memberMapper.toInquiryProfileResponse(inquiryMember, MemberRelation.OTHERS);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
public class AuthController {
private final AuthService authService;

@Operation(summary = "์†Œ์…œ ๋กœ๊ทธ์ธ", description = "๋„ค์ด๋ฒ„, ์นด์นด์˜ค, ๊ตฌ๊ธ€, ์• ํ”Œ ๋กœ๊ทธ์ธ")
@Operation(summary = "์†Œ์…œ ๋กœ๊ทธ์ธ API", description = "๋„ค์ด๋ฒ„, ์นด์นด์˜ค, ๊ตฌ๊ธ€ ๋กœ๊ทธ์ธ์„ ์ˆ˜ํ–‰ํ•˜๋Š” API์ž…๋‹ˆ๋‹ค.")
@ApiResponses(value = {
@ApiResponse(responseCode = "COMMON200", description = "๋กœ๊ทธ์ธ ์„ฑ๊ณต"),
@ApiResponse(responseCode = "AUTH007", description = "์™ธ๋ถ€ ์†Œ์…œ ์„œ๋ฒ„์™€์˜ ํ†ต์‹  ์—๋Ÿฌ" , content =
Expand Down
Loading

0 comments on commit 3533f79

Please sign in to comment.