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] 신고된 리그의 응원톡 전체 조회 #221

Merged
merged 17 commits into from
Sep 21, 2024
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
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
4 changes: 4 additions & 0 deletions src/docs/asciidoc/api.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ operation::cheer-talk-controller-test/응원톡을_저장한다[snippets='http-r

operation::cheer-talk-query-controller-test/응원톡을_조회한다[snippets='http-request,query-parameters,path-parameters,http-response,response-fields']

=== 신고된 리그의 응원톡 전체 조회

operation::cheer-talk-query-controller-test/리그의_신고된_응원톡을_조회한다[snippets='http-request,query-parameters,path-parameters,http-response,response-fields']

== 게임 API

=== 게임 상세 조회
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ SecurityFilterChain filterChain(HttpSecurity http, MvcRequestMatcher.Builder mvc
mvc.pattern(HttpMethod.PUT, "/leagues/{leagueId}/teams/{teamId}"),
mvc.pattern(HttpMethod.DELETE, "/leagues/{leagueId}/teams/{teamId}"),
mvc.pattern(HttpMethod.POST, "/leagues/{leagueId}/teams/{teamId}/delete-logo"),
mvc.pattern(HttpMethod.GET, "/leagues/{leagueId}/cheer-talks"),
mvc.pattern(HttpMethod.POST, "/leagues/{leagueId}/games"),
mvc.pattern(HttpMethod.POST, "/games/*/timelines/**"),
mvc.pattern(HttpMethod.POST, "/games/{gameId}/lineup-players/{lineupPlayerId}/**")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
package com.sports.server.query.application;

import com.sports.server.auth.exception.AuthorizationErrorMessages;
import com.sports.server.command.cheertalk.domain.CheerTalk;
import com.sports.server.command.league.domain.League;
import com.sports.server.command.member.domain.Member;
import com.sports.server.common.application.EntityUtils;
import com.sports.server.common.dto.PageRequestDto;
import com.sports.server.common.exception.UnauthorizedException;
import com.sports.server.query.dto.response.CheerTalkResponse;
import com.sports.server.query.dto.response.ReportedCheerTalkResponse;
import com.sports.server.query.repository.CheerTalkDynamicRepository;
import com.sports.server.query.repository.GameQueryRepository;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
Expand All @@ -18,6 +25,10 @@ public class CheerTalkQueryService {

private final CheerTalkDynamicRepository cheerTalkDynamicRepository;

private final GameQueryRepository gameQueryRepository;

private final EntityUtils entityUtils;

public List<CheerTalkResponse> getCheerTalksByGameId(final Long gameId, final PageRequestDto pageRequest) {
List<CheerTalk> cheerTalks = cheerTalkDynamicRepository.findByGameIdOrderByStartTime(
gameId, pageRequest.cursor(), pageRequest.size()
Expand All @@ -31,12 +42,22 @@ public List<CheerTalkResponse> getCheerTalksByGameId(final Long gameId, final Pa
return responses;
}

private List<Long> getOrderedGameTeamIds(final List<CheerTalk> cheerTalks) {
return cheerTalks.stream()
.map(CheerTalk::getGameTeamId)
.collect(Collectors.toSet())
.stream()
.sorted()
.toList();
public List<ReportedCheerTalkResponse> getReportedCheerTalksByLeagueId(final Long leagueId,
final PageRequestDto pageRequest,
final Member manager) {
League league = entityUtils.getEntity(leagueId, League.class);

if (!league.isManagedBy(manager)) {
throw new UnauthorizedException(AuthorizationErrorMessages.PERMISSION_DENIED);
}

List<CheerTalk> reportedCheerTalks = cheerTalkDynamicRepository.findReportedCheerTalksByLeagueId(
leagueId, pageRequest.cursor(), pageRequest.size()
);

return reportedCheerTalks.stream()
.map(cheerTalk -> new ReportedCheerTalkResponse(cheerTalk,
gameQueryRepository.findByIdWithLeague(cheerTalk.getGameTeamId()))).toList();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.sports.server.query.dto.response;

import com.sports.server.command.cheertalk.domain.CheerTalk;
import com.sports.server.command.game.domain.Game;
import java.time.LocalDateTime;

public record ReportedCheerTalkResponse(
Long cheerTalkId,
Long gameId,
Long leagueId,
String content,
Long gameTeamId,
LocalDateTime createdAt,
Boolean isBlocked,
String gameName,
String leagueName
) {
public ReportedCheerTalkResponse(CheerTalk cheerTalk, Game game) {
this(
cheerTalk.getId(),
game.getId(),
game.getLeague().getId(),
cheerTalk.getContent(),
cheerTalk.getGameTeamId(),
cheerTalk.getCreatedAt(),
cheerTalk.isBlocked(),
game.getName(),
game.getLeague().getName()
);
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package com.sports.server.query.presentation;

import com.sports.server.command.member.domain.Member;
import com.sports.server.common.dto.PageRequestDto;
import com.sports.server.query.application.CheerTalkQueryService;
import com.sports.server.query.dto.response.CheerTalkResponse;
import com.sports.server.query.dto.response.ReportedCheerTalkResponse;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
Expand All @@ -23,4 +25,11 @@ public ResponseEntity<List<CheerTalkResponse>> getAllCheerTalks(@PathVariable fi

return ResponseEntity.ok(cheerTalkQueryService.getCheerTalksByGameId(gameId, pageRequest));
}

@GetMapping("/leagues/{leagueId}/cheer-talks")
public ResponseEntity<List<ReportedCheerTalkResponse>> getAllReportedCheerTalks(@PathVariable final Long leagueId,
Jin409 marked this conversation as resolved.
Show resolved Hide resolved
@ModelAttribute final PageRequestDto pageRequest,
Member member) {
return ResponseEntity.ok(cheerTalkQueryService.getReportedCheerTalksByLeagueId(leagueId, pageRequest, member));
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
package com.sports.server.query.repository;

import com.sports.server.command.cheertalk.domain.CheerTalk;

import java.util.List;

public interface CheerTalkDynamicRepository {

List<CheerTalk> findByGameIdOrderByStartTime(Long gameId, Long cursor, Integer size);

List<CheerTalk> findReportedCheerTalksByLeagueId(Long leagueId, Long cursor, Integer size);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,13 @@

import static com.sports.server.command.cheertalk.domain.QCheerTalk.cheerTalk;
import static com.sports.server.command.game.domain.QGameTeam.gameTeam;
import static com.sports.server.command.report.domain.QReport.report;

import com.querydsl.core.types.dsl.BooleanExpression;
import com.querydsl.jpa.impl.JPAQuery;
import com.querydsl.jpa.impl.JPAQueryFactory;
import com.sports.server.command.cheertalk.domain.CheerTalk;
import com.sports.server.command.report.domain.ReportState;
import java.time.LocalDateTime;
import java.util.List;
import lombok.RequiredArgsConstructor;
Expand All @@ -19,19 +23,49 @@ public class CheerTalkDynamicRepositoryImpl implements CheerTalkDynamicRepositor
@Override
public List<CheerTalk> findByGameIdOrderByStartTime(Long gameId, Long cursor, Integer size) {
DynamicBooleanBuilder booleanBuilder = DynamicBooleanBuilder.builder();
return queryFactory.selectFrom(cheerTalk)
.join(gameTeam).on(cheerTalk.gameTeamId.eq(gameTeam.id))
.where(gameTeam.game.id.eq(gameId))
.where(booleanBuilder
.and(() -> cheerTalk.createdAt.loe(getCursorCreatedAt(cursor)))
.and(() -> cheerTalk.id.lt(cursor))
.build()
)

return applyPagination(
queryFactory.selectFrom(cheerTalk)
.join(gameTeam).on(cheerTalk.gameTeamId.eq(gameTeam.id))
.where(gameTeam.game.id.eq(gameId))
.where(booleanBuilder.build()),
Jin409 marked this conversation as resolved.
Show resolved Hide resolved
cursor,
size
);
}

@Override
public List<CheerTalk> findReportedCheerTalksByLeagueId(Long leagueId, Long cursor, Integer size) {
DynamicBooleanBuilder booleanBuilder = DynamicBooleanBuilder.builder();

return applyPagination(
queryFactory.selectFrom(cheerTalk)
.join(gameTeam).on(cheerTalk.gameTeamId.eq(gameTeam.id))
.join(report).on(report.cheerTalk.eq(cheerTalk))
.where(report.state.eq(ReportState.PENDING))
.where(gameTeam.game.league.id.eq(leagueId))
.where(booleanBuilder.build()),
Jin409 marked this conversation as resolved.
Show resolved Hide resolved
cursor,
size
);
}

private List<CheerTalk> applyPagination(JPAQuery<CheerTalk> query, Long cursor, Integer size) {
return query
.where(getPaginationConditions(cursor))
.orderBy(cheerTalk.createdAt.desc(), cheerTalk.id.desc())
.limit(size)
.fetch();
}

private BooleanExpression getPaginationConditions(Long cursor) {
if (cursor == null) {
return null;
}
return cheerTalk.createdAt.loe(getCursorCreatedAt(cursor))
.and(cheerTalk.id.lt(cursor));
}

private LocalDateTime getCursorCreatedAt(final Long cursor) {
if (cursor == null) {
return null;
Expand All @@ -42,4 +76,4 @@ private LocalDateTime getCursorCreatedAt(final Long cursor) {
.where(cheerTalk.id.eq(cursor))
.fetchFirst();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,11 @@ public interface GameQueryRepository extends Repository<Game, Long> {
+ "WHERE g.league=:league"
)
List<Game> findByLeagueWithGameTeams(@Param("league") League league);

@Query(
"SELECT g FROM Game g "
+ "JOIN FETCH g.league "
+ "WHERE g.id=:id"
)
Game findByIdWithLeague(@Param("id") Long id);
}
Loading
Loading