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

[fix] 지도뷰 조회 api, 핀내 미팅 조회 api 수정 #118

Merged
merged 5 commits into from
Feb 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
@@ -1,6 +1,5 @@
package org.pingle.pingleserver.controller;

import jakarta.annotation.Nullable;
import lombok.RequiredArgsConstructor;
import org.pingle.pingleserver.annotation.UserId;
import org.pingle.pingleserver.controller.swagger.PinApi;
Expand All @@ -23,16 +22,17 @@ public class PinController implements PinApi {
private final PinService pinService;

@GetMapping
public ApiResponse<List<PinResponse>> getPins (@PathVariable("teamId") Long teamId,
@Nullable @RequestParam("category")MCategory category) {
return ApiResponse.success(SuccessMessage.OK, pinService.getPins(teamId, category));
public ApiResponse<List<PinResponse>> getPins (@PathVariable Long teamId,
@RequestParam(required = false)MCategory category,
@RequestParam(required = false)String q) {
return ApiResponse.success(SuccessMessage.OK, pinService.getPins(teamId, category, q));
}

@GetMapping("/{pinId}/meetings")
public ApiResponse<List<MeetingResponse>> getMeetings(@UserId Long userId,
@PathVariable String teamId,
@PathVariable Long pinId,
@Nullable @RequestParam MCategory category) {
@RequestParam(required = false) MCategory category) {
return ApiResponse.success(SuccessMessage.OK, pinService.getMeetings(pinId, userId, category));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
public interface PinApi {

@Operation(summary = "핀 목록 조회", description = "핀 목록을 조회한다.")
ApiResponse<List<PinResponse>> getPins(Long teamId, MCategory category);
ApiResponse<List<PinResponse>> getPins(Long teamId, MCategory category, String q);

@Operation(summary = "핀에 속한 미팅 목록 조회", description = "핀에 속한 미팅 목록을 조회한다.")
ApiResponse<List<MeetingResponse>> getMeetings(@UserId Long userId,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,45 +1,6 @@
package org.pingle.pingleserver.dto.reponse;

import org.pingle.pingleserver.domain.Meeting;
import org.pingle.pingleserver.domain.Pin;
import org.pingle.pingleserver.domain.enums.MCategory;

import java.util.Comparator;
import java.util.List;

public record PinResponse(Long id, Double x, Double y, MCategory category, int meetingCount) {
public static PinResponse of(Pin pin, MCategory category, int count) {
return new PinResponse(pin.getId(),pin.getPoint().getX(), pin.getPoint().getY(),
category, count);
}
public static PinResponse ofWithNoFilter(Pin pin) {
return new PinResponse(pin.getId(),pin.getPoint().getX(), pin.getPoint().getY(),
getMostRecentMeetingCategoryOfPin(pin), getMeetingCount(pin));
}
public static PinResponse ofWithFilter(Pin pin, MCategory mCategory) {
return new PinResponse(pin.getId(),pin.getPoint().getX(), pin.getPoint().getY(),
mCategory, getMeetingCountWithFilter(pin, mCategory));

}
private static MCategory getMostRecentMeetingCategoryOfPin (Pin pin) {
Comparator<Meeting> comparator = Comparator.comparing(Meeting::getStartAt);
List<Meeting> meetingList = pin.getMeetingList();
meetingList.sort(comparator);
return meetingList.get(0).getCategory();
}

private static int getMeetingCount(Pin pin) {
return pin.getMeetingList().size();
}
private static int getMeetingCountWithFilter(Pin pin, MCategory category) {
int count = 0;
List<Meeting> meetings = pin.getMeetingList();
for(Meeting meeting : meetings) {
if(meeting.getCategory().getValue().equals(category.getValue()))
count++;
}

return count;
}

public record PinResponse(Long id, Double x, Double y, MCategory category) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,29 @@
import org.pingle.pingleserver.domain.Team;
import org.pingle.pingleserver.domain.Point;
import org.pingle.pingleserver.domain.enums.MCategory;
import org.pingle.pingleserver.dto.reponse.PinResponse;
import org.pingle.pingleserver.dto.response.RankingIndividualResponse;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;

import java.util.List;

public interface PinRepository extends JpaRepository<Pin, Long> {
List<Pin> findAllByTeam(Team team);
boolean existsByPointAndTeam(Point point, Team team);
Pin findByPointAndTeam(Point point, Team team);
@Query("SELECT DISTINCT p FROM Pin p WHERE p.team.id = :teamId AND p.id IN (SELECT m.pin.id FROM Meeting m WHERE m.startAt > CURRENT_TIMESTAMP AND m.category = :category)")
List<Pin> findPinsWithCategoryAndTimeBefore(Long teamId, MCategory category);
@Query("SELECT DISTINCT p FROM Pin p WHERE p.team.id = :teamId AND p.id IN (SELECT m.pin.id FROM Meeting m WHERE m.startAt > CURRENT_TIMESTAMP)")
List<Pin> findPinsAndTimeBefore(Long teamId);
@Query("select distinct new org.pingle.pingleserver.dto.reponse.PinResponse(p.id, p.point.x, p.point.y, m.category) from Pin p join p.meetingList m " +
"WHERE p.team.id = :teamId " +
"AND m.startAt > CURRENT_TIMESTAMP " +
"AND (m.category = :category OR :category IS NULL) " +
"AND (p.address.address LIKE concat('%' ,COALESCE(:q, ''), '%') OR p.name LIKE concat('%' ,COALESCE(:q, ''), '%')) " +
"AND m.startAt = (SELECT MIN(m.startAt) FROM Meeting m WHERE m.pin = p and m.startAt > CURRENT_TIMESTAMP AND (m.category = :category OR :category IS NULL)) ")
List<PinResponse> findPinsByTeamIdAndCategoryAndQ(Long teamId, MCategory category, String q);
@Query("select new org.pingle.pingleserver.dto.response.RankingIndividualResponse(p.name, max(m.endAt), count(p)) " +
"from Meeting m join m.pin p " +
"WHERE m.endAt < CURRENT_TIMESTAMP AND p.team.id = :teamId " +
"group by p " +
"order by count(p) desc, max(m.endAt) desc")
List<RankingIndividualResponse> findPinsWithMeetingsBeforeCurrentTimestampAndTeamId(Long teamId);

// todo: use native query to solve n+1 problem
// @Query(value = "SELECT p.*, COUNT(m.id) FROM pin p LEFT JOIN meeting m ON p.id = m.pin_id WHERE p.team_id = :teamId AND m.start_at > CURRENT_TIMESTAMP AND m.category = :category GROUP BY p.id", nativeQuery = true)
// List<PinResponse> test(Long teamId, MCategory category);
Expand Down
89 changes: 4 additions & 85 deletions src/main/java/org/pingle/pingleserver/service/PinService.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,10 @@
import org.pingle.pingleserver.repository.PinRepository;
import org.pingle.pingleserver.repository.TeamRepository;
import org.pingle.pingleserver.repository.UserMeetingRepository;
import org.pingle.pingleserver.utils.TimeUtil;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

@Slf4j
Expand All @@ -41,63 +38,6 @@ public class PinService {
private final MeetingRepository meetingRepository;
private final UserMeetingRepository userMeetingRepository;

public List<PinResponse> getPinsFilterByCategory(Long teamId, MCategory category) {
Team team = teamRepository.findByIdOrThrow(teamId);
List<Pin> pinList = pinRepository.findAllByTeam(team);
if(category == null) return pinList.stream().map(PinResponse::ofWithNoFilter).toList();
return pinList.stream().filter(pin -> checkMeetingsCategoryOfPin(pin, category))
.map(pin -> PinResponse.ofWithFilter(pin, category)).toList();
}

public List<MeetingResponse> getMeetingsDetail(Long userId, Long pinId, MCategory category) {
Pin pin = pinRepository.findById(pinId).orElseThrow(() -> new CustomException(ErrorMessage.RESOURCE_NOT_FOUND));
Comparator<Meeting> comparator = Comparator.comparing(Meeting::getStartAt);
List<Meeting> meetingList = pin.getMeetingList();
meetingList.sort(comparator);
List<MeetingResponse> responseList = new ArrayList<>();
if(category == null) {
for (Meeting meeting : meetingList) {
responseList.add(MeetingResponse.builder()
.id(meeting.getId())
.category(meeting.getCategory())
.name(meeting.getName())
.ownerName(meetingService.getOwnerName(meeting))
.location(pin.getName())
.date(TimeUtil.getDateFromDateTime(meeting.getStartAt()))
.startAt(TimeUtil.getTimeFromDateTime(meeting.getStartAt()))
.endAt(TimeUtil.getTimeFromDateTime(meeting.getEndAt()))
.maxParticipants(meeting.getMaxParticipants())
.curParticipants(getCurParticipants(meeting))
.isParticipating(isParticipating(userId, meeting))
.chatLink(meeting.getChatLink())
.isOwner(isOwner(userId, meeting.getId()))
.build());
}
return responseList;
}

for (Meeting meeting : meetingList) {
if(meeting.getCategory().getValue().equals(category.getValue())) {
responseList.add(MeetingResponse.builder()
.id(meeting.getId())
.category(meeting.getCategory())
.name(meeting.getName())
.ownerName(meetingService.getOwnerName(meeting))
.location(pin.getName())
.date(TimeUtil.getDateFromDateTime(meeting.getStartAt()))
.startAt(TimeUtil.getTimeFromDateTime(meeting.getStartAt()))
.endAt(TimeUtil.getTimeFromDateTime(meeting.getEndAt()))
.maxParticipants(meeting.getMaxParticipants())
.curParticipants(getCurParticipants(meeting))
.isParticipating(isParticipating(userId, meeting))
.chatLink(meeting.getChatLink())
.isOwner(isOwner(userId, meeting.getId()))
.build());
}
}
return responseList;
}

@Transactional
public Pin verifyAndReturnPin(MeetingRequest request, Long groupId) {
Team team = teamRepository.findByIdOrThrow(groupId);
Expand All @@ -112,22 +52,10 @@ public Pin verifyAndReturnPin(MeetingRequest request, Long groupId) {
return pinRepository.findByPointAndTeam(new Point(request.x(), request.y()), team);
}

public List<PinResponse> getPins(Long teamId, MCategory category) {
List<Pin> pins;

if (category == null) {
pins = pinRepository.findPinsAndTimeBefore(teamId);
return pins.stream().map(pin -> {
return PinResponse.of(
pin,
meetingRepository.findFirstByPinIdAndStartAtAfterOrderByStartAtAsc(pin.getId(), LocalDateTime.now())
.map(Meeting::getCategory).orElse(MCategory.OTHERS),
meetingRepository.countMeetingsForPinWithoutCategory(pin.getId()));
}).toList();
}
pins = pinRepository.findPinsWithCategoryAndTimeBefore(teamId, category);
return pins.stream()
.map(pin -> PinResponse.of(pin, category, meetingRepository.countMeetingsForPinWithCategory(pin.getId(), category))).toList();
public List<PinResponse> getPins(Long teamId, MCategory category, String q) {
if (q!=null && q.isBlank()) throw new CustomException(ErrorMessage.BAD_REQUEST);
if (!teamRepository.existsById(teamId)) throw new CustomException(ErrorMessage.RESOURCE_NOT_FOUND);
return pinRepository.findPinsByTeamIdAndCategoryAndQ(teamId, category, q);
}

public List<MeetingResponse> getMeetings(Long pinId, Long userId, MCategory category){
Expand All @@ -142,15 +70,6 @@ public List<MeetingResponse> getMeetings(Long pinId, Long userId, MCategory cate
.map(meeting -> MeetingResponse.of(meeting, meetingService.getOwnerName(meeting), getCurParticipants(meeting),
isParticipating(userId, meeting), isOwner(userId, meeting.getId()))).toList();
}

private boolean checkMeetingsCategoryOfPin(Pin pin, MCategory category) {
List<Meeting> meetingList = pin.getMeetingList();
for(Meeting meeting : meetingList) {
if(meeting.getCategory().getValue().equals(category.getValue()))
return true;
}
return false;
}

private int getCurParticipants(Meeting meeting) {
return userMeetingRepository.findAllByMeeting(meeting).size();
Expand Down
Loading