Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feat] 홈/검색 피드 API 구현 최종 #118

Merged
merged 24 commits into from
Jan 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
f162238
[rename] Rename 'MemberSearchFacade' to 'MemberFacade'
jo0oy Jan 24, 2024
f0b6ad0
[feat] 'PlaceListItemResponseDto' fromEntity() 메서드 '여행지 전화번호' 필드 mapp…
jo0oy Jan 24, 2024
728d693
[rename] Rename 'MemberListItemResponseDto' to 'MemberSimpleResponseDto'
jo0oy Jan 24, 2024
0fd88c2
[feat] 크리에이터 프로필 정보 응답 DTO 추가
jo0oy Jan 24, 2024
990d189
[feat] 회원 기본 정보 조회 서비스 로직 구현
jo0oy Jan 24, 2024
f372aab
[feat] 크리에이터 프로필 정보 조회 로직 구현
jo0oy Jan 24, 2024
e8cb550
[rename] Rename 'MemberSearchController' to 'MemberReadSearchController'
jo0oy Jan 24, 2024
b4284ab
[feat] 크리에이터 프로필 정보 조회 API 구현
jo0oy Jan 24, 2024
55f5c38
[rename] Rename 'MemberSearchService' to 'MemberReadSearchService'
jo0oy Jan 24, 2024
216736d
[rename] Rename 'MemberFacade' to 'MemberReadSearchFacade'
jo0oy Jan 24, 2024
92c03f3
[refactor] Move 'getMemberSimpleInfo' method from 'MemberService' to …
jo0oy Jan 24, 2024
b0db265
[test] MemberReadSearchFacadeTest 'getCreatorInfo' 로직 테스트 작성 및 확인
jo0oy Jan 24, 2024
ce21559
[feat] '/v1/members/**' permitAll 권한 설정 추가
jo0oy Jan 24, 2024
c4f9c5e
[feat] 홈 피드 인기 크리에이터 리스트 아이템 응답 DTO 'MemberInfoWithTripRecordsRespons…
jo0oy Jan 25, 2024
85554e8
[feat] TripRecordViewHistoryGroupByQueryDto 쿼리 DTO 추가
jo0oy Jan 25, 2024
b7060cc
[feat] TripRecordViewHistoryRepository 'findTopListMembers' 구현
jo0oy Jan 25, 2024
f0a75de
[refactor] TripRecordViewHistory 테이블 식별자 필드명 수정
jo0oy Jan 25, 2024
c3e3ccb
[remove] TripRecordCustomRepositoryImpl 불필요한 import 삭제
jo0oy Jan 25, 2024
9b069a7
[test] test-data-insert.sql TripRecordViewHistory 데이터 삽입 쿼리문 추가 및 Tri…
jo0oy Jan 25, 2024
0e7109f
[feat] 홈 피드 TOP 인기 크리에이터에 대한 기본 정보 리스트 조회 로직 구현
jo0oy Jan 25, 2024
902a8bc
[feat] 홈 피드 TOP 인기 크리에이터 조회 최종 응답 생성 로직 구현
jo0oy Jan 25, 2024
9d1fa9d
[test] MemberReadSearchFacadeTest 불필요한 로그 제거
jo0oy Jan 25, 2024
6eef135
[feat] 홈 피드 HOT 인기 크리에이터 리스트 조회 API 구현
jo0oy Jan 25, 2024
df20329
[rename] 도시 이미지 갤러리 응답 DTO 필드명 수정 및 제거
jo0oy Jan 25, 2024
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
Expand Up @@ -6,31 +6,28 @@
import lombok.Builder;

public record CityImageContentResponseDto(
Long id,
Long tripRecordId,
Integer storedCount,
String imageUrl
String imageUrl,
Integer tripRecordStoreCount
) {
@Builder
public CityImageContentResponseDto {
}

public static CityImageContentResponseDto fromEntity(TripRecordSchedule entity, TripRecordScheduleImage image) {
return CityImageContentResponseDto.builder()
.id(image.getId())
.tripRecordId(entity.getTripRecord().getId())
.storedCount(entity.getTripRecord().getStoreCount())
.imageUrl(image.getImageUrl())
.tripRecordStoreCount(entity.getTripRecord().getStoreCount())
.build();
}

public static CityImageContentResponseDto fromEntity(TripRecordScheduleImage entity) {
TripRecord tripRecord = entity.getTripRecordSchedule().getTripRecord();
return CityImageContentResponseDto.builder()
.id(entity.getId())
.tripRecordId(tripRecord.getId())
.storedCount(tripRecord.getStoreCount())
.imageUrl(entity.getImageUrl())
.tripRecordStoreCount(tripRecord.getStoreCount())
.build();
}
}
Original file line number Diff line number Diff line change
@@ -1,26 +1,37 @@
package com.haejwo.tripcometrue.domain.member.controller;

import com.haejwo.tripcometrue.domain.member.dto.response.MemberCreatorInfoResponseDto;
import com.haejwo.tripcometrue.domain.member.dto.response.MemberDetailListItemResponseDto;
import com.haejwo.tripcometrue.domain.member.dto.response.MemberSearchResultWithContentResponseDto;
import com.haejwo.tripcometrue.domain.member.facade.MemberSearchFacade;
import com.haejwo.tripcometrue.domain.member.facade.MemberReadSearchFacade;
import com.haejwo.tripcometrue.global.util.ResponseDTO;
import com.haejwo.tripcometrue.global.util.SliceResponseDto;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.web.PageableDefault;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;

@RequiredArgsConstructor
@RequestMapping("/v1/members")
@RestController
public class MemberSearchController {
public class MemberReadSearchController {

private final MemberSearchFacade memberSearchFacade;
private final MemberReadSearchFacade memberReadSearchFacade;

@GetMapping("/{memberId}")
public ResponseEntity<ResponseDTO<MemberCreatorInfoResponseDto>> memberCreatorInfo(
@PathVariable("memberId") Long memberId
) {
return ResponseEntity
.ok()
.body(
ResponseDTO.okWithData(
memberReadSearchFacade.getCreatorInfo(memberId)
)
);
}

@GetMapping("/list")
public ResponseEntity<ResponseDTO<MemberSearchResultWithContentResponseDto>> searchByNicknameResultWithContent(
Expand All @@ -30,7 +41,7 @@ public ResponseEntity<ResponseDTO<MemberSearchResultWithContentResponseDto>> sea
.ok()
.body(
ResponseDTO.okWithData(
memberSearchFacade.searchByNicknameResultWithContent(query)
memberReadSearchFacade.searchByNicknameResultWithContent(query)
)
);
}
Expand All @@ -44,7 +55,19 @@ public ResponseEntity<ResponseDTO<SliceResponseDto<MemberDetailListItemResponseD
.ok()
.body(
ResponseDTO.okWithData(
memberSearchFacade.searchByNicknamePagination(query, pageable)
memberReadSearchFacade.searchByNicknamePagination(query, pageable)
)
);
}

// 홈 피드 HOT 인기 크리에이터 리스트 조회
@GetMapping("/top-list")
public ResponseEntity<ResponseDTO<?>> listTopCreators() {
return ResponseEntity
.ok()
.body(
ResponseDTO.okWithData(
memberReadSearchFacade.listTopMemberCreators()
)
);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.haejwo.tripcometrue.domain.member.dto.response;

import com.haejwo.tripcometrue.domain.triprecord.dto.response.triprecord.TripRecordListItemResponseDto;
import com.haejwo.tripcometrue.domain.triprecord.dto.response.triprecord_schedule_media.TripRecordScheduleVideoListItemResponseDto;
import lombok.Builder;

import java.util.List;

public record MemberCreatorInfoResponseDto(
MemberDetailListItemResponseDto memberDetailInfo,
List<TripRecordScheduleVideoListItemResponseDto> videos,
List<TripRecordListItemResponseDto> tripRecords
) {

@Builder
public MemberCreatorInfoResponseDto {
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public record MemberDetailListItemResponseDto(
public MemberDetailListItemResponseDto {
}

public static MemberDetailListItemResponseDto of(MemberListItemResponseDto dto, Integer tripRecordTotal, Integer videoTotal) {
public static MemberDetailListItemResponseDto of(MemberSimpleResponseDto dto, Integer tripRecordTotal, Integer videoTotal) {
return MemberDetailListItemResponseDto.builder()
.memberId(dto.memberId())
.nickname(dto.nickname())
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.haejwo.tripcometrue.domain.member.dto.response;

import com.haejwo.tripcometrue.domain.triprecord.dto.response.triprecord.TripRecordListItemResponseDto;
import lombok.Builder;

import java.util.List;

public record MemberInfoWithTripRecordsResponseDto(
MemberSimpleResponseDto memberInfo,
List<TripRecordListItemResponseDto> tripRecords
) {

@Builder
public MemberInfoWithTripRecordsResponseDto {
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import java.util.List;

public record MemberSearchResultWithContentResponseDto(
List<MemberListItemResponseDto> members,
List<MemberSimpleResponseDto> members,
List<TripRecordScheduleVideoListItemResponseDto> videos,
List<TripRecordListItemResponseDto> tripRecords
) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import com.haejwo.tripcometrue.domain.member.entity.Member;
import lombok.Builder;

public record MemberListItemResponseDto(
public record MemberSimpleResponseDto(
Long memberId,
String nickname,
String introduction,
Expand All @@ -12,11 +12,11 @@ public record MemberListItemResponseDto(
) {

@Builder
public MemberListItemResponseDto {
public MemberSimpleResponseDto {
}

public static MemberListItemResponseDto fromEntity(Member entity) {
return MemberListItemResponseDto.builder()
public static MemberSimpleResponseDto fromEntity(Member entity) {
return MemberSimpleResponseDto.builder()
.memberId(entity.getId())
.nickname(entity.getMemberBase().getNickname())
.introduction(entity.getIntroduction())
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
package com.haejwo.tripcometrue.domain.member.facade;

import com.haejwo.tripcometrue.domain.member.dto.response.MemberDetailListItemResponseDto;
import com.haejwo.tripcometrue.domain.member.dto.response.MemberListItemResponseDto;
import com.haejwo.tripcometrue.domain.member.dto.response.MemberSearchResultWithContentResponseDto;
import com.haejwo.tripcometrue.domain.member.service.MemberSearchService;
import com.haejwo.tripcometrue.domain.member.dto.response.*;
import com.haejwo.tripcometrue.domain.member.service.MemberReadSearchService;
import com.haejwo.tripcometrue.domain.triprecord.dto.response.triprecord.TripRecordListItemResponseDto;
import com.haejwo.tripcometrue.domain.triprecord.dto.response.triprecord_schedule_media.TripRecordScheduleVideoListItemResponseDto;
import com.haejwo.tripcometrue.domain.triprecord.service.TripRecordScheduleVideoService;
Expand All @@ -14,6 +12,7 @@
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
Expand All @@ -22,18 +21,18 @@
@Slf4j
@RequiredArgsConstructor
@Service
public class MemberSearchFacade {
public class MemberReadSearchFacade {

private final MemberSearchService memberSearchService;
private final MemberReadSearchService memberReadSearchService;
private final TripRecordScheduleVideoService tripRecordScheduleVideoService;
private final TripRecordService tripRecordService;

public MemberSearchResultWithContentResponseDto searchByNicknameResultWithContent(String nickname) {
List<MemberListItemResponseDto> members = memberSearchService.searchByNickname(nickname);
List<MemberSimpleResponseDto> members = memberReadSearchService.searchByNickname(nickname);

List<Long> memberIds = members
.stream()
.map(MemberListItemResponseDto::memberId)
.map(MemberSimpleResponseDto::memberId)
.toList();

List<TripRecordScheduleVideoListItemResponseDto> videos = tripRecordScheduleVideoService.getVideosInMemberIds(memberIds);
Expand All @@ -48,16 +47,20 @@ public MemberSearchResultWithContentResponseDto searchByNicknameResultWithConten

public SliceResponseDto<MemberDetailListItemResponseDto> searchByNicknamePagination(String query, Pageable pageable) {

SliceResponseDto<MemberListItemResponseDto> sliceResult = memberSearchService.searchByNickname(query, pageable);
SliceResponseDto<MemberSimpleResponseDto> sliceResult = memberReadSearchService.searchByNickname(query, pageable);

List<Long> memberIds = sliceResult.content()
.stream()
.map(MemberListItemResponseDto::memberId)
.map(MemberSimpleResponseDto::memberId)
.toList();

Map<Long, List<TripRecordListItemResponseDto>> tripRecordMap = getGroupByMemberIdTripRecordMap(memberIds);
Map<Long, List<TripRecordListItemResponseDto>> tripRecordMap = getGroupByMemberIdTripRecordMap(
tripRecordService.findTripRecordsWihMemberInMemberIds(memberIds)
);

Map<Long, List<TripRecordScheduleVideoListItemResponseDto>> videoMap = getGroupByMemberIdVideoMap(memberIds);
Map<Long, List<TripRecordScheduleVideoListItemResponseDto>> videoMap = getGroupByMemberIdVideoMap(
tripRecordScheduleVideoService.getVideosInMemberIds(memberIds)
);


return SliceResponseDto.<MemberDetailListItemResponseDto>builder()
Expand All @@ -82,14 +85,61 @@ public SliceResponseDto<MemberDetailListItemResponseDto> searchByNicknamePaginat
.build();
}

private Map<Long, List<TripRecordScheduleVideoListItemResponseDto>> getGroupByMemberIdVideoMap(List<Long> memberIds) {
return tripRecordScheduleVideoService.getVideosInMemberIds(memberIds)
public MemberCreatorInfoResponseDto getCreatorInfo(Long memberId) {
MemberSimpleResponseDto memberInfo = memberReadSearchService.getMemberSimpleInfo(memberId);

List<TripRecordScheduleVideoListItemResponseDto> videos = tripRecordScheduleVideoService.getVideosInMemberIds(List.of(memberId));
List<TripRecordListItemResponseDto> tripRecords = tripRecordService.findTripRecordsWihMemberInMemberIds(List.of(memberId));

return MemberCreatorInfoResponseDto.builder()
.memberDetailInfo(
MemberDetailListItemResponseDto.of(
memberInfo, tripRecords.size(), videos.size()
)
)
.videos(videos)
.tripRecords(tripRecords)
.build();
}

public List<MemberInfoWithTripRecordsResponseDto> listTopMemberCreators() {
List<MemberSimpleResponseDto> memberSimpleInfos = memberReadSearchService.listTopMemberSimpleInfos();
log.info("memberSimpleInfo");


Map<Long, List<TripRecordListItemResponseDto>> tripRecordMap = getGroupByMemberIdTripRecordMap(
tripRecordService.findTripRecordsWihMemberInMemberIds(
memberSimpleInfos
.stream()
.map(MemberSimpleResponseDto::memberId)
.toList()
)
);

return memberSimpleInfos.stream()
.map(memberInfo -> MemberInfoWithTripRecordsResponseDto.builder()
.memberInfo(memberInfo)
.tripRecords(
Objects.nonNull(tripRecordMap.get(memberInfo.memberId())) ?
tripRecordMap.get(memberInfo.memberId()) : new ArrayList<>()
)
.build()
)
.toList();
}

private Map<Long, List<TripRecordScheduleVideoListItemResponseDto>> getGroupByMemberIdVideoMap(
List<TripRecordScheduleVideoListItemResponseDto> tripRecordScheduleVideos
) {
return tripRecordScheduleVideos
.stream()
.collect(Collectors.groupingBy(TripRecordScheduleVideoListItemResponseDto::memberId));
}

private Map<Long, List<TripRecordListItemResponseDto>> getGroupByMemberIdTripRecordMap(List<Long> memberIds) {
return tripRecordService.findTripRecordsWihMemberInMemberIds(memberIds)
private Map<Long, List<TripRecordListItemResponseDto>> getGroupByMemberIdTripRecordMap(
List<TripRecordListItemResponseDto> tripRecords
) {
return tripRecords
.stream()
.collect(Collectors.groupingBy(TripRecordListItemResponseDto::memberId));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package com.haejwo.tripcometrue.domain.member.service;

import com.haejwo.tripcometrue.domain.member.dto.response.MemberSimpleResponseDto;
import com.haejwo.tripcometrue.domain.member.exception.UserNotFoundException;
import com.haejwo.tripcometrue.domain.member.repository.MemberRepository;
import com.haejwo.tripcometrue.domain.triprecordViewHistory.repository.TripRecordViewHistoryRepository;
import com.haejwo.tripcometrue.global.util.SliceResponseDto;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

@RequiredArgsConstructor
@Service
public class MemberReadSearchService {

private final MemberRepository memberRepository;
private final TripRecordViewHistoryRepository tripRecordViewHistoryRepository;
private static final int HOME_TOP_CREATORS_SIZE = 10;

@Transactional(readOnly = true)
public MemberSimpleResponseDto getMemberSimpleInfo(Long memberId) {
return MemberSimpleResponseDto.fromEntity(
memberRepository.findById(memberId)
.orElseThrow(UserNotFoundException::new)
);
}

@Transactional(readOnly = true)
public List<MemberSimpleResponseDto> listTopMemberSimpleInfos() {
LocalDate current = LocalDate.now();
LocalDateTime start = current.minusDays(3).atStartOfDay();
LocalDateTime end = current.minusDays(1).atTime(23, 59, 59);

return tripRecordViewHistoryRepository
.findTopListMembers(start, end, HOME_TOP_CREATORS_SIZE)
.stream()
.map(dto -> MemberSimpleResponseDto.builder()
.memberId(dto.memberId())
.nickname(dto.nickname())
.introduction(dto.introduction())
.profileImageUrl(dto.profileImageUrl())
.build()
).toList();
}

@Transactional(readOnly = true)
public List<MemberSimpleResponseDto> searchByNickname(String nickname) {
return memberRepository
.findByNicknameOrderByMemberRating(nickname)
.stream()
.map(MemberSimpleResponseDto::fromEntity)
.toList();
}

@Transactional(readOnly = true)
public SliceResponseDto<MemberSimpleResponseDto> searchByNickname(String nickname, Pageable pageable) {

return SliceResponseDto.of(
memberRepository
.findByNicknameOrderByMemberRating(nickname, pageable)
.map(MemberSimpleResponseDto::fromEntity)
);
}
}
Loading
Loading