diff --git a/src/main/generated/com/gamegoo/domain/QFriend.java b/src/main/generated/com/gamegoo/domain/friend/QFriend.java similarity index 81% rename from src/main/generated/com/gamegoo/domain/QFriend.java rename to src/main/generated/com/gamegoo/domain/friend/QFriend.java index c2db7608..00197511 100644 --- a/src/main/generated/com/gamegoo/domain/QFriend.java +++ b/src/main/generated/com/gamegoo/domain/friend/QFriend.java @@ -1,4 +1,4 @@ -package com.gamegoo.domain; +package com.gamegoo.domain.friend; import static com.querydsl.core.types.PathMetadataFactory.*; @@ -16,7 +16,7 @@ @Generated("com.querydsl.codegen.DefaultEntitySerializer") public class QFriend extends EntityPathBase { - private static final long serialVersionUID = -762196062L; + private static final long serialVersionUID = -138403158L; private static final PathInits INITS = PathInits.DIRECT2; @@ -27,13 +27,13 @@ public class QFriend extends EntityPathBase { //inherited public final DateTimePath createdAt = _super.createdAt; - public final QMember fromMember; + public final com.gamegoo.domain.QMember fromMember; public final NumberPath id = createNumber("id", Long.class); public final BooleanPath isLiked = createBoolean("isLiked"); - public final QMember toMember; + public final com.gamegoo.domain.QMember toMember; //inherited public final DateTimePath updatedAt = _super.updatedAt; @@ -56,8 +56,8 @@ public QFriend(PathMetadata metadata, PathInits inits) { public QFriend(Class type, PathMetadata metadata, PathInits inits) { super(type, metadata, inits); - this.fromMember = inits.isInitialized("fromMember") ? new QMember(forProperty("fromMember")) : null; - this.toMember = inits.isInitialized("toMember") ? new QMember(forProperty("toMember")) : null; + this.fromMember = inits.isInitialized("fromMember") ? new com.gamegoo.domain.QMember(forProperty("fromMember")) : null; + this.toMember = inits.isInitialized("toMember") ? new com.gamegoo.domain.QMember(forProperty("toMember")) : null; } } diff --git a/src/main/generated/com/gamegoo/domain/QFriendRequests.java b/src/main/generated/com/gamegoo/domain/friend/QFriendRequests.java similarity index 78% rename from src/main/generated/com/gamegoo/domain/QFriendRequests.java rename to src/main/generated/com/gamegoo/domain/friend/QFriendRequests.java index 5dcc2e9c..3c075168 100644 --- a/src/main/generated/com/gamegoo/domain/QFriendRequests.java +++ b/src/main/generated/com/gamegoo/domain/friend/QFriendRequests.java @@ -1,4 +1,4 @@ -package com.gamegoo.domain; +package com.gamegoo.domain.friend; import static com.querydsl.core.types.PathMetadataFactory.*; @@ -16,7 +16,7 @@ @Generated("com.querydsl.codegen.DefaultEntitySerializer") public class QFriendRequests extends EntityPathBase { - private static final long serialVersionUID = -955592314L; + private static final long serialVersionUID = -1336304498L; private static final PathInits INITS = PathInits.DIRECT2; @@ -27,13 +27,13 @@ public class QFriendRequests extends EntityPathBase { //inherited public final DateTimePath createdAt = _super.createdAt; - public final QMember fromMember; + public final com.gamegoo.domain.QMember fromMember; public final NumberPath id = createNumber("id", Long.class); - public final BooleanPath isApproved = createBoolean("isApproved"); + public final EnumPath status = createEnum("status", FriendRequestStatus.class); - public final QMember toMember; + public final com.gamegoo.domain.QMember toMember; //inherited public final DateTimePath updatedAt = _super.updatedAt; @@ -56,8 +56,8 @@ public QFriendRequests(PathMetadata metadata, PathInits inits) { public QFriendRequests(Class type, PathMetadata metadata, PathInits inits) { super(type, metadata, inits); - this.fromMember = inits.isInitialized("fromMember") ? new QMember(forProperty("fromMember")) : null; - this.toMember = inits.isInitialized("toMember") ? new QMember(forProperty("toMember")) : null; + this.fromMember = inits.isInitialized("fromMember") ? new com.gamegoo.domain.QMember(forProperty("fromMember")) : null; + this.toMember = inits.isInitialized("toMember") ? new com.gamegoo.domain.QMember(forProperty("toMember")) : null; } } diff --git a/src/main/generated/com/gamegoo/domain/manner/QMannerRating.java b/src/main/generated/com/gamegoo/domain/manner/QMannerRating.java index d260b98e..a9e489c5 100644 --- a/src/main/generated/com/gamegoo/domain/manner/QMannerRating.java +++ b/src/main/generated/com/gamegoo/domain/manner/QMannerRating.java @@ -31,6 +31,8 @@ public class QMannerRating extends EntityPathBase { public final NumberPath id = createNumber("id", Long.class); + public final BooleanPath isPositive = createBoolean("isPositive"); + public final ListPath mannerRatingKeywordList = this.createList("mannerRatingKeywordList", MannerRatingKeyword.class, QMannerRatingKeyword.class, PathInits.DIRECT2); public final com.gamegoo.domain.QMember toMember; diff --git a/src/main/java/com/gamegoo/apiPayload/code/status/ErrorStatus.java b/src/main/java/com/gamegoo/apiPayload/code/status/ErrorStatus.java index 293e9e94..6cd189a8 100644 --- a/src/main/java/com/gamegoo/apiPayload/code/status/ErrorStatus.java +++ b/src/main/java/com/gamegoo/apiPayload/code/status/ErrorStatus.java @@ -41,7 +41,8 @@ public enum ErrorStatus implements BaseErrorCode { POSITION_NOT_FOUND(HttpStatus.NOT_FOUND, "POSITION404", "해당 Position을 찾을 수 없습니다."), // Profile_Image 관련 에러 - PROFILE_IMAGE_BAD_REQUEST(HttpStatus.BAD_REQUEST, "PROFILE_IMAGE400", "profile_image가 30자를 초과했습니다."), + PROFILE_IMAGE_BAD_REQUEST(HttpStatus.BAD_REQUEST, "PROFILE_IMAGE400", + "profile_image가 30자를 초과했습니다."), // Email 인증 관련 에러 EMAIL_SEND_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "EMAIL500", "이메일 전송 도중, 에러가 발생했습니다."), @@ -50,32 +51,37 @@ public enum ErrorStatus implements BaseErrorCode { EMAIL_INVALID_TIME(HttpStatus.BAD_REQUEST, "EMAIL400", "이메일 인증 시간이 3분 초과했습니다."), // 매칭 관련 에러 - MATCHING_STATUS_BAD_REQUEST(HttpStatus.BAD_REQUEST, "MATCH400", "status는 SUCCESS, QUIT 둘 중 하나로만 변경이 가능합니다."), + MATCHING_STATUS_BAD_REQUEST(HttpStatus.BAD_REQUEST, "MATCH400", + "status는 SUCCESS, QUIT 둘 중 하나로만 변경이 가능합니다."), MATCHING_NOT_FOUND(HttpStatus.NOT_FOUND, "MATCH404", "해당 사용자의 매칭 정보가 없습니다."), // Riot 관련 에러 RIOT_NOT_FOUND(HttpStatus.NOT_FOUND, "RIOT404", "해당 Riot 계정이 존재하지 않습니다."), - RIOT_MATCH_NOT_FOUND(HttpStatus.NOT_FOUND, "RIOTMATCH404", "해당 Riot 계정의 매칭을 불러오는 도중 에러가 발생했습니다. 최근 100판 이내 이벤트 매칭 제외, 일반 매칭(일반게임,랭크게임,칼바람)을 많이 한 계정으로 다시 시도하세요."), - RIOT_PREFER_CHAMPION_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "RIOTCHAMPION500", "선호 챔피언을 연동하는 도중 에러가 발생했습니다"), + RIOT_MATCH_NOT_FOUND(HttpStatus.NOT_FOUND, "RIOTMATCH404", + "해당 Riot 계정의 매칭을 불러오는 도중 에러가 발생했습니다. 최근 100판 이내 이벤트 매칭 제외, 일반 매칭(일반게임,랭크게임,칼바람)을 많이 한 계정으로 다시 시도하세요."), + RIOT_PREFER_CHAMPION_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "RIOTCHAMPION500", + "선호 챔피언을 연동하는 도중 에러가 발생했습니다"), CHAMPION_NOT_FOUND(HttpStatus.NOT_FOUND, "CHAMPION404", "해당 챔피언이 존재하지 않습니다."), RIOT_MEMBER_CONFLICT(HttpStatus.CONFLICT, "RIOT409", "해당 이메일 계정은 이미 다른 RIOT 계정과 연동되었습니다."), RIOT_ACCOUNT_CONFLICT(HttpStatus.CONFLICT, "RIOT409", "해당 RIOT 계정은 이미 다른 이메일과 연동되어있습니다."), RIOT_INSUFFICIENT_MATCHES(HttpStatus.NOT_FOUND, "RIOT404", - "해당 RIOT 계정은 최근 100판 이내에 솔로랭크, 자유랭크, 일반게임, 칼바람을 플레이한 적이 없기 때문에 선호하는 챔피언 3명을 정할 수 없습니다."), + "해당 RIOT 계정은 최근 100판 이내에 솔로랭크, 자유랭크, 일반게임, 칼바람을 플레이한 적이 없기 때문에 선호하는 챔피언 3명을 정할 수 없습니다."), RIOT_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "RIOT500", "RIOT API 연동 중 에러가 발생했습니다."), // 차단 관련 에러 TARGET_MEMBER_NOT_FOUND(HttpStatus.NOT_FOUND, "BLOCK401", "차단 대상 회원을 찾을 수 없습니다."), ALREADY_BLOCKED(HttpStatus.BAD_REQUEST, "BLOCK402", "이미 차단한 회원입니다."), TARGET_MEMBER_NOT_BLOCKED(HttpStatus.BAD_REQUEST, "BLOCK403", "차단 목록에 존재하지 않는 회원입니다."), + BLOCK_MEMBER_BAD_REQUEST(HttpStatus.BAD_REQUEST, "BLOCK404", "잘못된 친구 차단 요청입니다."), // 신고 관련 에러 REPORT_TARGET_MEMBER_NOT_FOUND(HttpStatus.NOT_FOUND, "REPORT401", "신고 대상 회원을 찾을 수 없습니다."), MEMBER_AND_TARGET_MEMBER_SAME(HttpStatus.BAD_REQUEST, "REPORT402", "회원과 신고 대상 회원이 같습니다."), // 게시판 글 작성 관련 에러 - BOARD_GAME_STYLE_BAD_REQUEST(HttpStatus.BAD_REQUEST, "BOARD400", "게임 스타일 선택 개수(최대 3개)를 초과했습니다."), + BOARD_GAME_STYLE_BAD_REQUEST(HttpStatus.BAD_REQUEST, "BOARD400", + "게임 스타일 선택 개수(최대 3개)를 초과했습니다."), GAME_MODE_INVALID(HttpStatus.BAD_REQUEST, "BOARD401", "게임모드 값은 1~4만 가능합니다."), MAIN_POSITION_INVALID(HttpStatus.BAD_REQUEST, "BOARD401", "주포지션 값은 1~5만 가능합니다."), SUB_POSITION_INVALID(HttpStatus.BAD_REQUEST, "BOARD401", "부포지션 값은 1~5만 가능합니다."), @@ -91,16 +97,26 @@ public enum ErrorStatus implements BaseErrorCode { // 매너평가 관련 에러 MANNER_TARGET_MEMBER_NOT_FOUND(HttpStatus.NOT_FOUND, "MANNER401", "매너 평가 대상 회원을 찾을 수 없습니다."), MANNER_KEYWORD_TYPE_INVALID(HttpStatus.BAD_REQUEST, "MANNER401", "매너 키워드 유형은 1~6만 가능합니다."), - BAD_MANNER_KEYWORD_TYPE_INVALID(HttpStatus.BAD_REQUEST, "MANNER401", "비매너 키워드 유형은 7~12만 가능합니다."), + BAD_MANNER_KEYWORD_TYPE_INVALID(HttpStatus.BAD_REQUEST, "MANNER401", + "비매너 키워드 유형은 7~12만 가능합니다."), MANNER_KEYWORD_NOT_FOUND(HttpStatus.NOT_FOUND, "MANNER404", "해당 매너 키워드를 찾을 수 없습니다."), MANNER_CONFLICT(HttpStatus.CONFLICT, "MANNER409", "매너 평가는 최초 1회만 가능합니다."), BAD_MANNER_CONFLICT(HttpStatus.CONFLICT, "MANNER409", "비매너 평가는 최초 1회만 가능합니다."), // 채팅 관련 에러 - CHAT_TARGET_NOT_FOUND(HttpStatus.NOT_FOUND, "CHAT4001", "채팅 대상 회원을 찾을 수 없습니다."), - CHATROOM_NOT_EXIST(HttpStatus.NOT_FOUND, "CHAT4002", "채팅방을 찾을 수 없습니다."), - CHATROOM_ACCESS_DENIED(HttpStatus.BAD_REQUEST, "CHAT4003", "접근할 수 없는 채팅방 입니다."), - CHAT_MESSAGE_NOT_FOUND(HttpStatus.NOT_FOUND, "CHAT4004", "해당 메시지를 찾을 수 없습니다"); + CHAT_TARGET_NOT_FOUND(HttpStatus.NOT_FOUND, "CHAT401", "채팅 대상 회원을 찾을 수 없습니다."), + CHATROOM_NOT_EXIST(HttpStatus.NOT_FOUND, "CHAT402", "채팅방을 찾을 수 없습니다."), + CHATROOM_ACCESS_DENIED(HttpStatus.BAD_REQUEST, "CHAT403", "접근할 수 없는 채팅방 입니다."), + CHAT_MESSAGE_NOT_FOUND(HttpStatus.NOT_FOUND, "CHAT404", "해당 메시지를 찾을 수 없습니다"), + + // 친구 관련 에러 + FRIEND_BAD_REQUEST(HttpStatus.BAD_REQUEST, "FRIEND401", "잘못된 친구 요청입니다."), + FRIEND_TARGET_IS_BLOCKED(HttpStatus.BAD_REQUEST, "FRIEND402", + "내가 차단한 회원입니다. 친구 요청을 보낼 수 없습니다."), + BLOCKED_BY_FRIEND_TARGET(HttpStatus.BAD_REQUEST, "FRIEND403", + "나를 차단한 회원입니다. 친구 요청을 보낼 수 없습니다."), + + ; private final HttpStatus httpStatus; private final String code; @@ -109,19 +125,19 @@ public enum ErrorStatus implements BaseErrorCode { @Override public ErrorReasonDTO getReason() { return ErrorReasonDTO.builder() - .message(message) - .code(code) - .isSuccess(false) - .build(); + .message(message) + .code(code) + .isSuccess(false) + .build(); } @Override public ErrorReasonDTO getReasonHttpStatus() { return ErrorReasonDTO.builder() - .message(message) - .code(code) - .isSuccess(false) - .httpStatus(httpStatus) - .build(); + .message(message) + .code(code) + .isSuccess(false) + .httpStatus(httpStatus) + .build(); } } diff --git a/src/main/java/com/gamegoo/apiPayload/exception/handler/FriendHandler.java b/src/main/java/com/gamegoo/apiPayload/exception/handler/FriendHandler.java new file mode 100644 index 00000000..8fde6871 --- /dev/null +++ b/src/main/java/com/gamegoo/apiPayload/exception/handler/FriendHandler.java @@ -0,0 +1,11 @@ +package com.gamegoo.apiPayload.exception.handler; + +import com.gamegoo.apiPayload.code.BaseErrorCode; +import com.gamegoo.apiPayload.exception.GeneralException; + +public class FriendHandler extends GeneralException { + + public FriendHandler(BaseErrorCode code) { + super(code); + } +} diff --git a/src/main/java/com/gamegoo/controller/member/MemberController.java b/src/main/java/com/gamegoo/controller/member/BlockController.java similarity index 67% rename from src/main/java/com/gamegoo/controller/member/MemberController.java rename to src/main/java/com/gamegoo/controller/member/BlockController.java index 7a6fb613..d120767e 100644 --- a/src/main/java/com/gamegoo/controller/member/MemberController.java +++ b/src/main/java/com/gamegoo/controller/member/BlockController.java @@ -2,16 +2,13 @@ import com.gamegoo.apiPayload.ApiResponse; import com.gamegoo.converter.MemberConverter; -import com.gamegoo.domain.Friend; import com.gamegoo.domain.Member; import com.gamegoo.dto.member.MemberResponse; -import com.gamegoo.service.member.MemberService; +import com.gamegoo.service.member.BlockService; import com.gamegoo.util.JWTUtil; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; -import java.util.List; -import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.data.domain.Page; @@ -24,58 +21,45 @@ import org.springframework.web.bind.annotation.RestController; @Slf4j -@Tag(name = "Member", description = "회원 관련 API") +@Tag(name = "Block", description = "회원 차단 관련 API") @RestController @RequiredArgsConstructor -@RequestMapping("/v1/member") -public class MemberController { +@RequestMapping("/v1/member/block") +public class BlockController { - private final MemberService memberService; + private final BlockService blockService; @Operation(summary = "회원 차단 API", description = "대상 회원을 차단하는 API 입니다.") @Parameter(name = "memberId", description = "차단할 대상 회원의 id 입니다.") - @PostMapping("/block/{memberId}") + @PostMapping("/{memberId}") public ApiResponse blockMember(@PathVariable(name = "memberId") Long targetMemberId) { Long memberId = JWTUtil.getCurrentUserId(); //헤더에 있는 jwt 토큰에서 id를 가져오는 코드 - memberService.blockMember(memberId, targetMemberId); + blockService.blockMember(memberId, targetMemberId); return ApiResponse.onSuccess("회원 차단 성공"); } @Operation(summary = "차단한 회원 목록 조회 API", description = "내가 차단한 회원의 목록을 조회하는 API 입니다.") @Parameter(name = "page", description = "페이지 번호, 1 이상의 숫자를 입력해 주세요.") - @GetMapping("/block") + @GetMapping public ApiResponse getBlockList( @RequestParam(name = "page") Integer page) { Long memberId = JWTUtil.getCurrentUserId(); - Page blockList = memberService.getBlockList(memberId, page - 1); + Page blockList = blockService.getBlockList(memberId, page - 1); return ApiResponse.onSuccess(MemberConverter.toBlockListDTO(blockList)); } @Operation(summary = "회원 차단 해제 API", description = "해당 회원에 대한 차단을 해제하는 API 입니다.") @Parameter(name = "memberId", description = "차단을 해제할 대상 회원의 id 입니다.") - @DeleteMapping("/block/{memberId}") + @DeleteMapping("/{memberId}") public ApiResponse unBlockMember(@PathVariable(name = "memberId") Long targetMemberId) { Long memberId = JWTUtil.getCurrentUserId(); - memberService.unBlockMember(memberId, targetMemberId); + blockService.unBlockMember(memberId, targetMemberId); return ApiResponse.onSuccess("차단 해제 성공"); } - @Operation(summary = "친구 목록 조회 API", description = "해당 회원의 친구 목록을 조회하는 API 입니다.") - @GetMapping("/friends") - public ApiResponse getFriendList() { - Long memberId = JWTUtil.getCurrentUserId(); - List friends = memberService.getFriends(memberId); - - List friendInfoDTOList = friends.stream() - .map(MemberConverter::toFriendInfoDto).collect( - Collectors.toList()); - - return ApiResponse.onSuccess(friendInfoDTOList); - - } } diff --git a/src/main/java/com/gamegoo/controller/member/FriendController.java b/src/main/java/com/gamegoo/controller/member/FriendController.java new file mode 100644 index 00000000..87e6e612 --- /dev/null +++ b/src/main/java/com/gamegoo/controller/member/FriendController.java @@ -0,0 +1,61 @@ +package com.gamegoo.controller.member; + +import com.gamegoo.apiPayload.ApiResponse; +import com.gamegoo.converter.MemberConverter; +import com.gamegoo.domain.friend.Friend; +import com.gamegoo.domain.friend.FriendRequests; +import com.gamegoo.dto.member.MemberResponse; +import com.gamegoo.service.member.FriendService; +import com.gamegoo.util.JWTUtil; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import java.util.List; +import java.util.stream.Collectors; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@Slf4j +@Tag(name = "Friend", description = "친구 관련 API") +@RestController +@RequiredArgsConstructor +@RequestMapping("/v1/friends") +public class FriendController { + + private final FriendService friendService; + + @Operation(summary = "친구 목록 조회 API", description = "해당 회원의 친구 목록을 조회하는 API 입니다.") + @GetMapping + public ApiResponse> getFriendList() { + Long memberId = JWTUtil.getCurrentUserId(); + List friends = friendService.getFriends(memberId); + + List friendInfoDTOList = friends.stream() + .map(MemberConverter::toFriendInfoDto).collect( + Collectors.toList()); + + return ApiResponse.onSuccess(friendInfoDTOList); + + } + + @Operation(summary = "친구 요청 전송 API", description = "대상 회원에게 친구 요청을 전송하는 API 입니다." + + "대상 회원에게 친구 요청 알림을 전송하며, 대상 회원이 현재 접속 중인 경우 socket을 통해 실시간 알림을 전송합니다.") + @Parameter(name = "memberId", description = "친구 요청을 전송할 대상 회원의 id 입니다.") + @PostMapping("/send/{memberId}") + public ApiResponse sendFriendRequest( + @PathVariable(name = "memberId") Long targetMemberId) { + Long memberId = JWTUtil.getCurrentUserId(); + + FriendRequests friendRequests = friendService.sendFriendRequest(memberId, targetMemberId); + + return ApiResponse.onSuccess("친구 요청 전송 성공"); + + } + + +} diff --git a/src/main/java/com/gamegoo/converter/MemberConverter.java b/src/main/java/com/gamegoo/converter/MemberConverter.java index 4f99948c..b4e221ac 100644 --- a/src/main/java/com/gamegoo/converter/MemberConverter.java +++ b/src/main/java/com/gamegoo/converter/MemberConverter.java @@ -1,38 +1,37 @@ package com.gamegoo.converter; -import com.gamegoo.domain.Friend; import com.gamegoo.domain.Member; +import com.gamegoo.domain.friend.Friend; import com.gamegoo.dto.member.MemberResponse; -import org.springframework.data.domain.Page; - import java.util.List; import java.util.stream.Collectors; +import org.springframework.data.domain.Page; public class MemberConverter { public static MemberResponse.blockListDTO toBlockListDTO(Page blockList) { List blockedMemberDtoList = blockList.stream() - .map(MemberConverter::toBlockedMemberDTO) - .collect(Collectors.toList()); + .map(MemberConverter::toBlockedMemberDTO) + .collect(Collectors.toList()); return MemberResponse.blockListDTO.builder() - .blockedMemberDTOList(blockedMemberDtoList) - .listSize(blockedMemberDtoList.size()) - .totalPage(blockList.getTotalPages()) - .totalElements(blockList.getTotalElements()) - .isFirst(blockList.isFirst()) - .isLast(blockList.isLast()) - .build(); + .blockedMemberDTOList(blockedMemberDtoList) + .listSize(blockedMemberDtoList.size()) + .totalPage(blockList.getTotalPages()) + .totalElements(blockList.getTotalElements()) + .isFirst(blockList.isFirst()) + .isLast(blockList.isLast()) + .build(); } public static MemberResponse.blockedMemberDTO toBlockedMemberDTO(Member member) { return MemberResponse.blockedMemberDTO.builder() - .memberId(member.getId()) - .profileImg(member.getProfileImage()) - .email(member.getEmail()) - .name(member.getGameName()) - .build(); + .memberId(member.getId()) + .profileImg(member.getProfileImage()) + .email(member.getEmail()) + .name(member.getGameName()) + .build(); } @@ -40,42 +39,41 @@ public static MemberResponse.myProfileMemberDTO toMyProfileDTO(Member member) { List gameStyleResponseDTOList = null; if (member.getMemberGameStyleList() != null) { gameStyleResponseDTOList = member.getMemberGameStyleList().stream() - .map(memberGameStyle -> MemberResponse.GameStyleResponseDTO.builder() - .gameStyleId(memberGameStyle.getGameStyle().getId()) - .gameStyleName(memberGameStyle.getGameStyle().getStyleName()) - .build()).collect(Collectors.toList()); + .map(memberGameStyle -> MemberResponse.GameStyleResponseDTO.builder() + .gameStyleId(memberGameStyle.getGameStyle().getId()) + .gameStyleName(memberGameStyle.getGameStyle().getStyleName()) + .build()).collect(Collectors.toList()); } List championResponseDTOList = null; if (member.getMemberChampionList() != null) { championResponseDTOList = member.getMemberChampionList().stream() - .map(memberChampion -> MemberResponse.ChampionResponseDTO.builder() - .championId(memberChampion.getMember().getId()) - .championName(memberChampion.getChampion().getName()) - .build()).collect(Collectors.toList()); + .map(memberChampion -> MemberResponse.ChampionResponseDTO.builder() + .championId(memberChampion.getMember().getId()) + .championName(memberChampion.getChampion().getName()) + .build()).collect(Collectors.toList()); } - return MemberResponse.myProfileMemberDTO.builder() - .email(member.getEmail()) - .gameName(member.getGameName()) - .tag(member.getTag()) - .tier(member.getTier()) - .rank(member.getRank()) - .profileImg(member.getProfileImage()) - .updatedAt(String.valueOf(member.getUpdatedAt())) - .gameStyleResponseDTOList(gameStyleResponseDTOList) - .championResponseDTOList(championResponseDTOList) - .build(); + .email(member.getEmail()) + .gameName(member.getGameName()) + .tag(member.getTag()) + .tier(member.getTier()) + .rank(member.getRank()) + .profileImg(member.getProfileImage()) + .updatedAt(String.valueOf(member.getUpdatedAt())) + .gameStyleResponseDTOList(gameStyleResponseDTOList) + .championResponseDTOList(championResponseDTOList) + .build(); } public static MemberResponse.friendInfoDTO toFriendInfoDto(Friend friend) { return MemberResponse.friendInfoDTO.builder() - .memberId(friend.getToMember().getId()) - .name(friend.getToMember().getGameName()) - .memberProfileImg(friend.getToMember().getProfileImage()) - .isLiked(friend.getIsLiked()) - .build(); + .memberId(friend.getToMember().getId()) + .name(friend.getToMember().getGameName()) + .memberProfileImg(friend.getToMember().getProfileImage()) + .isLiked(friend.getIsLiked()) + .build(); } } diff --git a/src/main/java/com/gamegoo/domain/Friend.java b/src/main/java/com/gamegoo/domain/friend/Friend.java similarity index 93% rename from src/main/java/com/gamegoo/domain/Friend.java rename to src/main/java/com/gamegoo/domain/friend/Friend.java index 2f6d48b2..a464b0c6 100644 --- a/src/main/java/com/gamegoo/domain/Friend.java +++ b/src/main/java/com/gamegoo/domain/friend/Friend.java @@ -1,5 +1,6 @@ -package com.gamegoo.domain; +package com.gamegoo.domain.friend; +import com.gamegoo.domain.Member; import com.gamegoo.domain.common.BaseDateTimeEntity; import javax.persistence.Column; import javax.persistence.Entity; diff --git a/src/main/java/com/gamegoo/domain/friend/FriendRequestStatus.java b/src/main/java/com/gamegoo/domain/friend/FriendRequestStatus.java new file mode 100644 index 00000000..94c5bff4 --- /dev/null +++ b/src/main/java/com/gamegoo/domain/friend/FriendRequestStatus.java @@ -0,0 +1,9 @@ +package com.gamegoo.domain.friend; + +public enum FriendRequestStatus { + PENDING, // 대기중 + ACCEPTED, // 수락됨 + REJECTED, // 거절됨 + CANCELLED // 취소됨 + +} diff --git a/src/main/java/com/gamegoo/domain/FriendRequests.java b/src/main/java/com/gamegoo/domain/friend/FriendRequests.java similarity index 78% rename from src/main/java/com/gamegoo/domain/FriendRequests.java rename to src/main/java/com/gamegoo/domain/friend/FriendRequests.java index 0f647945..d745c247 100644 --- a/src/main/java/com/gamegoo/domain/FriendRequests.java +++ b/src/main/java/com/gamegoo/domain/friend/FriendRequests.java @@ -1,8 +1,11 @@ -package com.gamegoo.domain; +package com.gamegoo.domain.friend; +import com.gamegoo.domain.Member; import com.gamegoo.domain.common.BaseDateTimeEntity; import javax.persistence.Column; import javax.persistence.Entity; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; @@ -27,8 +30,9 @@ public class FriendRequests extends BaseDateTimeEntity { @Column(name = "friend_request_id") private Long id; - @Column(nullable = false) - private Boolean isApproved; + @Enumerated(EnumType.STRING) + @Column(columnDefinition = "VARCHAR(30)", nullable = false) + private FriendRequestStatus status; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "from_member_id", nullable = false) diff --git a/src/main/java/com/gamegoo/dto/member/MemberResponse.java b/src/main/java/com/gamegoo/dto/member/MemberResponse.java index df994ce9..3c5292c2 100644 --- a/src/main/java/com/gamegoo/dto/member/MemberResponse.java +++ b/src/main/java/com/gamegoo/dto/member/MemberResponse.java @@ -1,8 +1,11 @@ package com.gamegoo.dto.member; -import lombok.*; - import java.util.List; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; public class MemberResponse { @@ -11,6 +14,7 @@ public class MemberResponse { @NoArgsConstructor @AllArgsConstructor public static class blockListDTO { + List blockedMemberDTOList; Integer listSize; Integer totalPage; @@ -25,6 +29,7 @@ public static class blockListDTO { @NoArgsConstructor @AllArgsConstructor public static class blockedMemberDTO { + Long memberId; String profileImg; String email; @@ -99,4 +104,5 @@ public static class friendInfoDTO { String memberProfileImg; boolean isLiked; } + } diff --git a/src/main/java/com/gamegoo/repository/member/FriendRepository.java b/src/main/java/com/gamegoo/repository/friend/FriendRepository.java similarity index 73% rename from src/main/java/com/gamegoo/repository/member/FriendRepository.java rename to src/main/java/com/gamegoo/repository/friend/FriendRepository.java index 8d31248f..fd59bbb3 100644 --- a/src/main/java/com/gamegoo/repository/member/FriendRepository.java +++ b/src/main/java/com/gamegoo/repository/friend/FriendRepository.java @@ -1,6 +1,6 @@ -package com.gamegoo.repository.member; +package com.gamegoo.repository.friend; -import com.gamegoo.domain.Friend; +import com.gamegoo.domain.friend.Friend; import java.util.List; import org.springframework.data.jpa.repository.JpaRepository; diff --git a/src/main/java/com/gamegoo/repository/friend/FriendRequestsRepository.java b/src/main/java/com/gamegoo/repository/friend/FriendRequestsRepository.java new file mode 100644 index 00000000..8cc0fe7f --- /dev/null +++ b/src/main/java/com/gamegoo/repository/friend/FriendRequestsRepository.java @@ -0,0 +1,8 @@ +package com.gamegoo.repository.friend; + +import com.gamegoo.domain.friend.FriendRequests; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface FriendRequestsRepository extends JpaRepository { + +} diff --git a/src/main/java/com/gamegoo/service/member/MemberService.java b/src/main/java/com/gamegoo/service/member/BlockService.java similarity index 83% rename from src/main/java/com/gamegoo/service/member/MemberService.java rename to src/main/java/com/gamegoo/service/member/BlockService.java index 3fa19a3a..943e94ab 100644 --- a/src/main/java/com/gamegoo/service/member/MemberService.java +++ b/src/main/java/com/gamegoo/service/member/BlockService.java @@ -5,12 +5,10 @@ import com.gamegoo.apiPayload.exception.handler.MemberHandler; import com.gamegoo.apiPayload.exception.handler.PageHandler; import com.gamegoo.domain.Block; -import com.gamegoo.domain.Friend; import com.gamegoo.domain.Member; import com.gamegoo.repository.member.BlockRepository; -import com.gamegoo.repository.member.FriendRepository; import com.gamegoo.repository.member.MemberRepository; -import java.util.List; +import com.gamegoo.util.MemberUtils; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; @@ -20,11 +18,10 @@ @Service @RequiredArgsConstructor @Transactional -public class MemberService { +public class BlockService { private final MemberRepository memberRepository; private final BlockRepository blockRepository; - private final FriendRepository friendRepository; Integer pageSize = 9; @@ -42,8 +39,13 @@ public Member blockMember(Long memberId, Long targetMemberId) { Member targetMember = memberRepository.findById(targetMemberId) .orElseThrow(() -> new MemberHandler(ErrorStatus.TARGET_MEMBER_NOT_FOUND)); + // 본인이 본인을 차단 시도하는 경우 + if (member.equals(targetMember)) { + throw new MemberHandler(ErrorStatus.BLOCK_MEMBER_BAD_REQUEST); + } + // 대상 회원의 탈퇴 여부 검증 - checkBlind(targetMember); + MemberUtils.checkBlind(targetMember); // 이미 차단한 회원인지 검증 boolean isblocked = blockRepository.existsByBlockerMemberAndBlockedMember(member, @@ -107,28 +109,5 @@ public void unBlockMember(Long memberId, Long targetMemberId) { blockRepository.delete(block); } - /** - * memberId에 해당하는 회원의 친구 목록 조회 - * - * @param memberId - * @return - */ - @Transactional(readOnly = true) - public List getFriends(Long memberId) { - return friendRepository.findAllByFromMemberId(memberId); - } - - /** - * 해당 회원이 탈퇴했는지 검증 - * - * @param member - */ - public static boolean checkBlind(Member member) { - if (member.getBlind()) { - throw new MemberHandler(ErrorStatus.USER_DEACTIVATED); - } - return false; - } - } diff --git a/src/main/java/com/gamegoo/service/member/FriendService.java b/src/main/java/com/gamegoo/service/member/FriendService.java new file mode 100644 index 00000000..b40b4048 --- /dev/null +++ b/src/main/java/com/gamegoo/service/member/FriendService.java @@ -0,0 +1,72 @@ +package com.gamegoo.service.member; + +import com.gamegoo.apiPayload.code.status.ErrorStatus; +import com.gamegoo.apiPayload.exception.handler.FriendHandler; +import com.gamegoo.domain.Member; +import com.gamegoo.domain.friend.Friend; +import com.gamegoo.domain.friend.FriendRequestStatus; +import com.gamegoo.domain.friend.FriendRequests; +import com.gamegoo.repository.friend.FriendRepository; +import com.gamegoo.repository.friend.FriendRequestsRepository; +import com.gamegoo.util.MemberUtils; +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@RequiredArgsConstructor +@Transactional +public class FriendService { + + private final FriendRepository friendRepository; + private final FriendRequestsRepository friendRequestsRepository; + private final ProfileService profileService; + + /** + * memberId에 해당하는 회원의 친구 목록 조회 + * + * @param memberId + * @return + */ + @Transactional(readOnly = true) + public List getFriends(Long memberId) { + return friendRepository.findAllByFromMemberId(memberId); + } + + + /** + * targetMemberId에 해당하는 회원에게 친구 요청 전송 + * + * @param memberId + * @param targetMemberId + * @return + */ + public FriendRequests sendFriendRequest(Long memberId, Long targetMemberId) { + Member member = profileService.findMember(memberId); + + Member targetMember = profileService.findMember(targetMemberId); + + if (member.equals(targetMember)) { + throw new FriendHandler(ErrorStatus.FRIEND_BAD_REQUEST); + } + + // 내가 상대방을 차단한 경우 + if (MemberUtils.isBocked(member, targetMember)) { + throw new FriendHandler(ErrorStatus.FRIEND_TARGET_IS_BLOCKED); + } + + // 상대방이 나를 차단한 경우 + if (MemberUtils.isBocked(targetMember, member)) { + throw new FriendHandler(ErrorStatus.BLOCKED_BY_FRIEND_TARGET); + } + + FriendRequests friendRequests = FriendRequests.builder() + .status(FriendRequestStatus.PENDING) + .fromMember(member) + .toMember(targetMember) + .build(); + + return friendRequestsRepository.save(friendRequests); + } +} diff --git a/src/main/java/com/gamegoo/util/MemberUtils.java b/src/main/java/com/gamegoo/util/MemberUtils.java new file mode 100644 index 00000000..6a7a6b7d --- /dev/null +++ b/src/main/java/com/gamegoo/util/MemberUtils.java @@ -0,0 +1,35 @@ +package com.gamegoo.util; + +import com.gamegoo.apiPayload.code.status.ErrorStatus; +import com.gamegoo.apiPayload.exception.handler.MemberHandler; +import com.gamegoo.domain.Member; + +public class MemberUtils { + + /** + * member가 targetMember를 차단한 상태인지 리턴 + * + * @param member + * @param targetMember + * @return + */ + public static boolean isBocked(Member member, Member targetMember) { + + return member.getBlockList().stream() + .anyMatch(block -> block.getBlockedMember().equals(targetMember)); + } + + /** + * 해당 회원이 탈퇴했는지 검증 + * + * @param member + */ + public static boolean checkBlind(Member member) { + if (member.getBlind()) { + throw new MemberHandler(ErrorStatus.USER_DEACTIVATED); + } + return false; + } + + +}