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 all 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/reported"),
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,15 @@
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.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,25 +24,40 @@ public class CheerTalkQueryService {

private final CheerTalkDynamicRepository cheerTalkDynamicRepository;

public List<CheerTalkResponse> getCheerTalksByGameId(final Long gameId, final PageRequestDto pageRequest) {
private final GameQueryRepository gameQueryRepository;

private final EntityUtils entityUtils;

public List<CheerTalkResponse.ForSpectator> getCheerTalksByGameId(final Long gameId,
final PageRequestDto pageRequest) {
List<CheerTalk> cheerTalks = cheerTalkDynamicRepository.findByGameIdOrderByStartTime(
gameId, pageRequest.cursor(), pageRequest.size()
);

List<CheerTalkResponse> responses = cheerTalks.stream()
.map(CheerTalkResponse::new)
List<CheerTalkResponse.ForSpectator> responses = cheerTalks.stream()
.map(CheerTalkResponse.ForSpectator::new)
.collect(Collectors.toList());

Collections.reverse(responses);
return responses;
}

private List<Long> getOrderedGameTeamIds(final List<CheerTalk> cheerTalks) {
return cheerTalks.stream()
.map(CheerTalk::getGameTeamId)
.collect(Collectors.toSet())
.stream()
.sorted()
.toList();
public List<CheerTalkResponse.Reported> 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 CheerTalkResponse.Reported(cheerTalk,
gameQueryRepository.findByIdWithLeague(cheerTalk.getGameTeamId()))).toList();
}

}
Original file line number Diff line number Diff line change
@@ -1,29 +1,61 @@
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 CheerTalkResponse(
Long cheerTalkId,
String content,
Long gameTeamId,
LocalDateTime createdAt,
Boolean isBlocked
) {
public CheerTalkResponse(CheerTalk cheerTalk) {
this(
cheerTalk.getId(),
checkCheerTalkIsBlocked(cheerTalk),
cheerTalk.getGameTeamId(),
cheerTalk.getCreatedAt(),
cheerTalk.isBlocked()
);
public class CheerTalkResponse {
public record ForSpectator(
Long cheerTalkId,
String content,
Long gameTeamId,
LocalDateTime createdAt,
Boolean isBlocked
) {
public ForSpectator(CheerTalk cheerTalk) {
this(
cheerTalk.getId(),
checkCheerTalkIsBlocked(cheerTalk),
cheerTalk.getGameTeamId(),
cheerTalk.getCreatedAt(),
cheerTalk.isBlocked()
);
}

private static String checkCheerTalkIsBlocked(CheerTalk cheerTalk) {
if (cheerTalk.isBlocked()) {
return null;
}
return cheerTalk.getContent();
}
}

private static String checkCheerTalkIsBlocked(CheerTalk cheerTalk) {
if (cheerTalk.isBlocked()) {
return null;
public record Reported(
Long cheerTalkId,
Long gameId,
Long leagueId,
String content,
Long gameTeamId,
LocalDateTime createdAt,
Boolean isBlocked,
String gameName,
String leagueName
) {
public Reported(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()
);
}
return cheerTalk.getContent();
}


}

Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public void handle(CheerTalkCreateEvent event) {

messagingTemplate.convertAndSend(
DESTINATION + game.getId(),
new CheerTalkResponse(cheerTalk)
new CheerTalkResponse.ForSpectator(cheerTalk)
);

}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
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;
Expand All @@ -18,9 +19,16 @@ public class CheerTalkQueryController {
private final CheerTalkQueryService cheerTalkQueryService;

@GetMapping("games/{gameId}/cheer-talks")
public ResponseEntity<List<CheerTalkResponse>> getAllCheerTalks(@PathVariable final Long gameId,
@ModelAttribute final PageRequestDto pageRequest) {
public ResponseEntity<List<CheerTalkResponse.ForSpectator>> getAllCheerTalks(@PathVariable final Long gameId,
@ModelAttribute final PageRequestDto pageRequest) {

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

@GetMapping("/leagues/{leagueId}/cheer-talks/reported")
public ResponseEntity<List<CheerTalkResponse.Reported>> getAllReportedCheerTalks(@PathVariable final Long leagueId,
@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 @@ -18,20 +22,44 @@ 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)),
cursor,
size
);
}

@Override
public List<CheerTalk> findReportedCheerTalksByLeagueId(Long leagueId, Long cursor, Integer size) {
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)),
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 +70,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);
}
34 changes: 20 additions & 14 deletions src/main/resources/static/docs/api.html
Original file line number Diff line number Diff line change
Expand Up @@ -1601,7 +1601,7 @@ <h4 id="_게임_등록_http_request"><a class="link" href="#_게임_등록_http_
"round" : "16강",
"quarter" : "경기전",
"state" : "SCHEDULED",
"startTime" : "2024-09-19T19:34:01.751883",
"startTime" : "2024-09-18T18:41:01.634111",
"idOfTeam1" : 1,
"idOfTeam2" : 2,
"videoId" : "videoId"
Expand Down Expand Up @@ -1908,15 +1908,16 @@ <h4 id="_리그_생성_http_request"><a class="link" href="#_리그_생성_http_
<div class="content">
<pre class="highlightjs highlight nowrap"><code class="language-http hljs" data-lang="http">POST /leagues HTTP/1.1
Content-Type: application/json
Content-Length: 150
Content-Length: 179
Host: www.api.hufstreaming.site
Cookie: HCC_SES=temp-cookie

{
"organizationId" : 1,
"name" : "우물정 제기차기 대회",
"maxRound" : 4,
"startAt" : "2024-09-19T19:34:02.040614",
"endAt" : "2024-09-19T19:34:02.040618"
"maxRound" : "4강",
"startAt" : "2024-09-18T18:41:01.840974",
"endAt" : "2024-09-18T18:41:01.840975"
}</code></pre>
</div>
</div>
Expand All @@ -1938,14 +1939,19 @@ <h4 id="_리그_생성_request_fields"><a class="link" href="#_리그_생성_req
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>organizationId</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>Number</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">조직 id</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>name</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>String</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">대회 이름</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>maxRound</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>Number</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">대회 진행 라운드 수. 결승은 2</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>String</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">대회 진행 라운드 수</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>startAt</code></p></td>
Expand Down Expand Up @@ -1986,8 +1992,8 @@ <h4 id="_리그_수정_http_request"><a class="link" href="#_리그_수정_http_

{
"name" : "훕치치배 망고 빨리먹기 대회",
"startAt" : "2024-09-19T19:34:02.059989",
"endAt" : "2024-09-19T19:34:02.059994",
"startAt" : "2024-09-18T18:41:01.856257",
"endAt" : "2024-09-18T18:41:01.856261",
"maxRound" : "16강"
}</code></pre>
</div>
Expand Down Expand Up @@ -2867,12 +2873,12 @@ <h4 id="_매니저가_생성한_리그_전체_조회_http_response"><a class="li
"state" : "진행 중",
"sizeOfLeagueTeams" : 2,
"maxRound" : "16강",
"startAt" : "2024-09-19T19:34:05.926666",
"endAt" : "2024-09-19T19:34:05.926666",
"startAt" : "2024-09-18T18:41:05.056959",
"endAt" : "2024-09-18T18:41:05.056959",
"inProgressGames" : [ {
"id" : 1,
"state" : "PLAYING",
"startTime" : "2024-09-19T19:34:05.926657",
"startTime" : "2024-09-18T18:41:05.056951",
"gameTeams" : [ {
"gameTeamId" : 1,
"gameTeamName" : "경영 야생마",
Expand Down Expand Up @@ -4111,7 +4117,7 @@ <h4 id="_사용자_로그인_http_response"><a class="link" href="#_사용자_
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Set-Cookie: HCC_SES=testAccessToken; Path=/; Max-Age=604800; Expires=Thu, 26 Sep 2024 10:33:57 GMT; Secure; HttpOnly; SameSite=Strict</code></pre>
Set-Cookie: HCC_SES=testAccessToken; Path=/; Max-Age=604800; Expires=Wed, 25 Sep 2024 09:40:56 GMT; Secure; HttpOnly; SameSite=Strict</code></pre>
</div>
</div>
</div>
Expand Down Expand Up @@ -4185,7 +4191,7 @@ <h4 id="_사용자_정보_조회_response_fields"><a class="link" href="#_사용
<div id="footer">
<div id="footer-text">
Version 0.0.1-SNAPSHOT<br>
Last updated 2024-09-19 18:35:26 +0900
Last updated 2024-09-18 18:40:18 +0900
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.18.3/highlight.min.js"></script>
Expand Down
Loading
Loading