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: 추천 모임 목록 조회 구현 #523

Merged
merged 7 commits into from
Jan 7, 2025
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
package org.sopt.makers.crew.main.entity.meeting;

import java.util.List;

import org.sopt.makers.crew.main.global.util.Time;
import org.sopt.makers.crew.main.meeting.v2.dto.query.MeetingV2GetAllMeetingQueryDto;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;

public interface MeetingSearchRepository {
Page<Meeting> findAllByQuery(MeetingV2GetAllMeetingQueryDto queryCommand, Pageable pageable, Time time);

List<Meeting> findRecommendMeetings(List<Integer> meetingIds, Time time);
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@
@RequiredArgsConstructor
public class MeetingSearchRepositoryImpl implements MeetingSearchRepository {
private final JPAQueryFactory queryFactory;
//private final Time time;

/**
* @note: canJoinOnlyActiveGeneration 처리 유의
Expand All @@ -48,6 +47,26 @@ public Page<Meeting> findAllByQuery(MeetingV2GetAllMeetingQueryDto queryCommand,
PageRequest.of(pageable.getPageNumber(), pageable.getPageSize()), countQuery::fetchFirst);
}

/**
* @param meetingIds : 조회하려는 모임 id 리스트
* @implSpec : meetingIds 가 null 인 경우, '지금 모집중인 모임' 반환
* */
@Override
public List<Meeting> findRecommendMeetings(List<Integer> meetingIds, Time time) {

JPAQuery<Meeting> query = queryFactory.selectFrom(meeting)
.innerJoin(meeting.user, user)
.fetchJoin();

if (meetingIds == null) {
query.where(eqStatus(List.of(String.valueOf(EnMeetingStatus.APPLY_ABLE.getValue())), time));
return query.fetch();
}

query.where(meeting.id.in(meetingIds));
return query.fetch();
}

private List<Meeting> getMeetings(MeetingV2GetAllMeetingQueryDto queryCommand, Pageable pageable, Time time) {
return queryFactory
.selectFrom(meeting)
Expand Down Expand Up @@ -153,7 +172,7 @@ private BooleanExpression eqJoinableParts(MeetingJoinablePart[] joinableParts) {

// SQL 템플릿을 사용하여 BooleanExpression 생성
return Expressions.booleanTemplate(
"arraycontains({0}, "+ joinablePartsToString + ") || '' = 'true'",
"arraycontains({0}, " + joinablePartsToString + ") || '' = 'true'",
meeting.joinableParts,
joinablePartsToString
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,13 @@
import org.sopt.makers.crew.main.meeting.v2.dto.response.MeetingV2GetAllMeetingDto;
import org.sopt.makers.crew.main.meeting.v2.dto.response.MeetingV2GetMeetingBannerResponseDto;
import org.sopt.makers.crew.main.meeting.v2.dto.response.MeetingV2GetMeetingByIdResponseDto;
import org.sopt.makers.crew.main.meeting.v2.dto.response.MeetingV2GetRecommendDto;
import org.sopt.makers.crew.main.meeting.v2.dto.response.PreSignedUrlResponseDto;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
Expand Down Expand Up @@ -134,4 +136,12 @@ ResponseEntity<AppliesCsvFileUrlResponseDto> getAppliesCsvFileUrl(
@ApiResponse(responseCode = "400", description = "모임이 없습니다.", content = @Content),})
ResponseEntity<MeetingV2GetMeetingByIdResponseDto> getMeetingById(@PathVariable Integer meetingId,
Principal principal);

@Operation(summary = "추천 모임 목록 조회", description = "추천 모임 목록 조회, 쿼리파라미터가 없는 경우 '지금 모집중인 모임' 반환")
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "추천 모임 목록 조회 성공"),
@ApiResponse(responseCode = "400", description = "모임이 없습니다.", content = @Content)
})
ResponseEntity<MeetingV2GetRecommendDto> getRecommendMeetingsByIds(
@RequestParam(name = "meetingIds", required = false) @Parameter(description = "추천할 모임들의 ID 리스트", example = "[101, 102, 103]") List<Integer> meetingIds,
Principal principal);
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import org.sopt.makers.crew.main.meeting.v2.dto.response.MeetingV2GetAllMeetingDto;
import org.sopt.makers.crew.main.meeting.v2.dto.response.MeetingV2GetMeetingBannerResponseDto;
import org.sopt.makers.crew.main.meeting.v2.dto.response.MeetingV2GetMeetingByIdResponseDto;
import org.sopt.makers.crew.main.meeting.v2.dto.response.MeetingV2GetRecommendDto;
import org.sopt.makers.crew.main.meeting.v2.dto.response.PreSignedUrlResponseDto;
import org.sopt.makers.crew.main.meeting.v2.service.MeetingV2Service;
import org.springframework.http.HttpStatus;
Expand Down Expand Up @@ -196,4 +197,14 @@ public ResponseEntity<MeetingV2GetMeetingByIdResponseDto> getMeetingById(@PathVa

return ResponseEntity.ok(meetingV2Service.getMeetingById(meetingId, userId));
}

@Override
@GetMapping("/recommend")
public ResponseEntity<MeetingV2GetRecommendDto> getRecommendMeetingsByIds(
@RequestParam(name = "meetingIds", required = false) List<Integer> meetingIds,
Principal principal) {
Integer userId = UserUtil.getUserId(principal);

return ResponseEntity.ok().body(meetingV2Service.getRecommendMeetingsByIds(meetingIds, userId));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package org.sopt.makers.crew.main.meeting.v2.dto.response;

import java.util.List;

import org.sopt.makers.crew.main.global.dto.MeetingResponseDto;

import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;

@Schema(name = "MeetingV2GetRecommendDto", description = "추천 모임 목록 조회 응답 Dto")
public record MeetingV2GetRecommendDto(
@Schema(description = "모임 객체 목록", example = "")
@NotNull
List<MeetingResponseDto> meetings
) {
public static MeetingV2GetRecommendDto from(List<MeetingResponseDto> meetings) {
return new MeetingV2GetRecommendDto(meetings);
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import org.sopt.makers.crew.main.meeting.v2.dto.response.MeetingV2GetAllMeetingDto;
import org.sopt.makers.crew.main.meeting.v2.dto.response.MeetingV2GetMeetingBannerResponseDto;
import org.sopt.makers.crew.main.meeting.v2.dto.response.MeetingV2GetMeetingByIdResponseDto;
import org.sopt.makers.crew.main.meeting.v2.dto.response.MeetingV2GetRecommendDto;

public interface MeetingV2Service {

Expand Down Expand Up @@ -47,4 +48,6 @@ AppliesCsvFileUrlResponseDto getAppliesCsvFileUrl(Integer meetingId, List<Intege
Integer userId);

MeetingV2GetMeetingByIdResponseDto getMeetingById(Integer meetingId, Integer userId);

MeetingV2GetRecommendDto getRecommendMeetingsByIds(List<Integer> meetingIds, Integer userId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@
import org.sopt.makers.crew.main.meeting.v2.dto.response.MeetingV2GetMeetingBannerResponseDto;
import org.sopt.makers.crew.main.meeting.v2.dto.response.MeetingV2GetMeetingBannerResponseUserDto;
import org.sopt.makers.crew.main.meeting.v2.dto.response.MeetingV2GetMeetingByIdResponseDto;
import org.sopt.makers.crew.main.meeting.v2.dto.response.MeetingV2GetRecommendDto;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Caching;
import org.springframework.data.domain.Page;
Expand Down Expand Up @@ -448,6 +449,22 @@ public MeetingV2GetMeetingByIdResponseDto getMeetingById(Integer meetingId, Inte
meetingLeader, applyWholeInfoDtos, time.now());
}

@Override
public MeetingV2GetRecommendDto getRecommendMeetingsByIds(List<Integer> meetingIds, Integer userId) {

List<Meeting> meetings = meetingRepository.findRecommendMeetings(meetingIds, time);
List<Integer> foundMeetingIds = meetings.stream().map(Meeting::getId).toList();

Applies allApplies = new Applies(applyRepository.findAllByMeetingIdIn(foundMeetingIds));

List<MeetingResponseDto> meetingResponseDtos = meetings.stream()
.map(meeting -> MeetingResponseDto.of(meeting, meeting.getUser(),
allApplies.getApprovedCount(meeting.getId()), time.now()))
.toList();

return MeetingV2GetRecommendDto.from(meetingResponseDtos);
}

private void deleteCsvFile(String filePath) {
try {
Files.deleteIfExists(Paths.get(filePath));
Expand Down
Loading