Skip to content

Commit

Permalink
Merge pull request #114 from TeamPINGLE/feat/112
Browse files Browse the repository at this point in the history
[feat] 리스트뷰 검색 api 생성
  • Loading branch information
Parkjyun authored Feb 15, 2024
2 parents 52f1eb5 + 64dc9cd commit 45e6b20
Show file tree
Hide file tree
Showing 6 changed files with 135 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,12 @@
import org.pingle.pingleserver.controller.swagger.MeetingApi;
import org.pingle.pingleserver.domain.Meeting;
import org.pingle.pingleserver.domain.Pin;
import org.pingle.pingleserver.domain.enums.MCategory;
import org.pingle.pingleserver.domain.enums.SearchOrder;
import org.pingle.pingleserver.dto.common.ApiResponse;
import org.pingle.pingleserver.dto.request.MeetingRequest;
import org.pingle.pingleserver.dto.response.ParticipantsResponse;
import org.pingle.pingleserver.dto.response.SearchResponse;
import org.pingle.pingleserver.dto.type.SuccessMessage;
import org.pingle.pingleserver.service.MeetingService;
import org.pingle.pingleserver.service.PinService;
Expand Down Expand Up @@ -60,4 +63,14 @@ public ApiResponse<?> deleteMeeting(@UserId Long userId, @PathVariable("meetingI
meetingService.deleteMeeting(userId, meetingId);
return ApiResponse.success(SuccessMessage.OK);
}

@GetMapping("/search")
public ApiResponse<SearchResponse> getSearchResult(@UserId Long userId,
@RequestParam(required = false) String q,
@RequestParam(required = false) MCategory category,
@RequestParam Long teamId,
@RequestParam SearchOrder order) {
return ApiResponse.success(SuccessMessage.OK, meetingService.searchMeetings(userId , q, category, teamId, order));
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package org.pingle.pingleserver.domain.enums;

import lombok.Getter;
import lombok.RequiredArgsConstructor;

@Getter
@RequiredArgsConstructor
public enum SearchOrder {
NEW("new"), UPCOMING("upcoming");
private final String value;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package org.pingle.pingleserver.dto.response;

import lombok.Builder;
import org.pingle.pingleserver.domain.Meeting;
import org.pingle.pingleserver.domain.UserMeeting;
import org.pingle.pingleserver.domain.enums.MCategory;
import org.pingle.pingleserver.domain.enums.MRole;
import org.pingle.pingleserver.dto.type.ErrorMessage;
import org.pingle.pingleserver.exception.CustomException;
import org.pingle.pingleserver.utils.TimeUtil;

import java.util.List;

@Builder
public record SearchIndividualResponse(Long id,MCategory category, String name, String ownerName,
String location, String date, String startAt, String endAt, int maxParticipants,
int curParticipants, boolean isParticipating, String chatLink, boolean isOwner) {

public static SearchIndividualResponse of (Meeting meeting, Long userId) {
return new SearchIndividualResponse(meeting.getId(), meeting.getCategory(), meeting.getName(), getOwnerName(meeting),
meeting.getPin().getName(), TimeUtil.getDateFromDateTime(meeting.getStartAt()),
TimeUtil.getTimeFromDateTime(meeting.getStartAt()), TimeUtil.getTimeFromDateTime(meeting.getEndAt()),
meeting.getMaxParticipants(), meeting.getUserMeetingList().size(),
isParticipating(meeting, userId), meeting.getChatLink(), isOwner(meeting, userId));
}

private static String getOwnerName(Meeting meeting) {
List<UserMeeting> userMeetings = meeting.getUserMeetingList();
if(userMeetings.isEmpty()) throw new CustomException(ErrorMessage.RESOURCE_NOT_FOUND);
for (UserMeeting userMeeting : userMeetings) {
if(userMeeting.getMeetingRole().equals(MRole.OWNER)) return userMeeting.getUser().getValidName();
}
return null;
}

private static boolean isParticipating(Meeting meeting, Long userId) {
List<UserMeeting> userMeetings = meeting.getUserMeetingList();
for (UserMeeting userMeeting : userMeetings) {
if(userMeeting.getUser().getId().equals(userId)) return true;
}
return false;
}
private static boolean isOwner(Meeting meeting, Long userId) {
List<UserMeeting> userMeetings = meeting.getUserMeetingList();
for (UserMeeting userMeeting : userMeetings) {
if (userMeeting.getMeetingRole().equals(MRole.OWNER) && userMeeting.getUser().getId().equals(userId)) return true;
}
return false;
}

}

Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package org.pingle.pingleserver.dto.response;

import java.util.List;

public record SearchResponse(int searchCount, List<SearchIndividualResponse> meetings) {
public static SearchResponse of(List<SearchIndividualResponse> meetings) {
return new SearchResponse(meetings.size(),meetings);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,21 @@ public interface MeetingRepository extends JpaRepository<Meeting, Long> {
List<Meeting> findByPinIdAndCategoryAndStartAtAfterOrderByStartAt(Long pinId, MCategory category, LocalDateTime currentTime);

List<Meeting> findByPinIdAndStartAtAfterOrderByStartAt(Long pinId, LocalDateTime currentTime);

@Query("SELECT m " +
"FROM Meeting m JOIN FETCH m.pin p join fetch m.userMeetingList um join FETCH um.user join fetch p.team t " +
"WHERE t.id = :teamId AND m.startAt > CURRENT_TIMESTAMP " +
"AND (m.category = :category OR :category IS NULL) " + //+
"AND (m.name LIKE concat('%' ,COALESCE(:q, ''), '%') OR p.name LIKE concat('%' ,COALESCE(:q, ''), '%') OR p.address.address LIKE concat('%' ,COALESCE(:q, ''), '%')) " +
"ORDER BY m.createdAt DESC")
List<Meeting> findMeetingsByParameterOOrderByCreatedAt(String q, MCategory category, Long teamId);

@Query("SELECT m " +
"FROM Meeting m JOIN FETCH m.pin p join fetch m.userMeetingList um join FETCH um.user join fetch p.team t " +
"WHERE t.id = :teamId AND m.startAt > CURRENT_TIMESTAMP " +
"AND (m.category = :category OR :category IS NULL) " +
"AND (m.name LIKE concat('%' ,COALESCE(:q, ''), '%') OR p.name LIKE concat('%' ,COALESCE(:q, ''), '%') OR p.address.address LIKE concat('%' ,COALESCE(:q, ''), '%')) " +
"ORDER BY m.startAt ASC")
List<Meeting> findMeetingsByParameterOOrderByStartAt(String q, MCategory category, Long teamId);

}
40 changes: 33 additions & 7 deletions src/main/java/org/pingle/pingleserver/service/MeetingService.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,18 @@
import org.pingle.pingleserver.domain.Meeting;
import org.pingle.pingleserver.domain.Pin;
import org.pingle.pingleserver.domain.UserMeeting;
import org.pingle.pingleserver.domain.enums.MCategory;
import org.pingle.pingleserver.domain.enums.MRole;
import org.pingle.pingleserver.domain.enums.SearchOrder;
import org.pingle.pingleserver.dto.request.MeetingRequest;
import org.pingle.pingleserver.dto.response.MyPingleResponse;
import org.pingle.pingleserver.dto.response.ParticipantsResponse;
import org.pingle.pingleserver.dto.response.SearchIndividualResponse;
import org.pingle.pingleserver.dto.response.SearchResponse;
import org.pingle.pingleserver.dto.type.ErrorMessage;
import org.pingle.pingleserver.exception.CustomException;
import org.pingle.pingleserver.repository.MeetingRepository;
import org.pingle.pingleserver.repository.TeamRepository;
import org.pingle.pingleserver.repository.UserMeetingRepository;
import org.pingle.pingleserver.utils.SlackUtil;
import org.springframework.stereotype.Service;
Expand All @@ -20,6 +25,7 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
Expand All @@ -29,6 +35,7 @@ public class MeetingService {
private final SlackUtil slackUtil;
private final MeetingRepository meetingRepository;
private final UserMeetingRepository userMeetingRepository;
private final TeamRepository teamRepository;

@Transactional
public Meeting createMeeting(MeetingRequest request, Pin pin) {
Expand All @@ -55,34 +62,53 @@ public ParticipantsResponse getParticipants(Long meetingId) {

public List<MyPingleResponse> getMyPingles(Long userId, Long teamId, boolean participation) {
List<Meeting> myMeetings = new ArrayList<>();
if(participation) // 참여 완려 -> 이미 시작 endAt 이 현재보다 빠름
myMeetings = meetingRepository.findParticipatedMeetingsForUsersInTeamOrderByTime(userId, teamId, LocalDateTime.now());
if(!participation) // 참여하지 않은 것 == 나중에 일어날 것 -> endAt이 현재보다 늦음
if (participation) // 참여 완려 -> 이미 시작 endAt 이 현재보다 빠름
myMeetings = meetingRepository.findParticipatedMeetingsForUsersInTeamOrderByTime(userId, teamId, LocalDateTime.now());
if (!participation) // 참여하지 않은 것 == 나중에 일어날 것 -> endAt이 현재보다 늦음
myMeetings = meetingRepository.findUnparticipatedMeetingsForUsersInTeamOrderByTime(userId, teamId, LocalDateTime.now());
return myMeetings.stream()
.map(meeting -> MyPingleResponse.of(meeting, getOwnerName(meeting), isOwner(userId, meeting.getId()))).toList();
}

public String getOwnerName(Meeting meeting){
public String getOwnerName(Meeting meeting) {
Optional<UserMeeting> userMeeting = userMeetingRepository.findByMeetingAndMeetingRole(meeting, MRole.OWNER);
if (userMeeting.isPresent()) {
return userMeeting.get().getUser().getValidName();
} else {
return "(알 수 없음)";
}
}

private boolean isOwner(Long userId, Long meetingId) {
return userMeetingRepository.existsByUserIdAndMeetingIdAndMeetingRole(userId, meetingId, MRole.OWNER);
}

@Transactional
public void deleteMeeting(Long userId, Long meetingId) {
Meeting meeting = meetingRepository.findById(meetingId).orElseThrow(() -> new CustomException(ErrorMessage.RESOURCE_NOT_FOUND));
UserMeeting userMeeting = userMeetingRepository.findByUserIdAndMeeting(userId, meeting).orElseThrow(() -> new CustomException(ErrorMessage.RESOURCE_NOT_FOUND));
if(userMeeting.getMeetingRole().getValue().equals("participants"))
if (userMeeting.getMeetingRole().getValue().equals("participants"))
throw new CustomException(ErrorMessage.PERMISSION_DENIED);
meetingRepository.delete(meeting);
}

public SearchResponse searchMeetings(Long userId, String q, MCategory category, Long teamId, SearchOrder order) {

if (q!=null && q.isBlank()) throw new CustomException(ErrorMessage.BAD_REQUEST);
if (!teamRepository.existsById(teamId)) throw new CustomException(ErrorMessage.RESOURCE_NOT_FOUND);

if (order.getValue().equals(SearchOrder.NEW.getValue())) {
List<SearchIndividualResponse> responses = meetingRepository.findMeetingsByParameterOOrderByCreatedAt(q, category ,teamId)
.stream().map(meeting -> SearchIndividualResponse.of(meeting, userId)).collect(Collectors.toList());
return SearchResponse.of(responses);
}

if (order.getValue().equals(SearchOrder.UPCOMING.getValue())) {
List<SearchIndividualResponse> responses = meetingRepository.findMeetingsByParameterOOrderByStartAt(q, category, teamId)
.stream().map(meeting -> SearchIndividualResponse.of(meeting, userId)).collect(Collectors.toList());
return SearchResponse.of(responses);
}
return null;
}
}

0 comments on commit 45e6b20

Please sign in to comment.