Skip to content

Commit

Permalink
Merge pull request #226 from hufscheer/feat/#217-league
Browse files Browse the repository at this point in the history
[FEAT] 매니저가 관리하는 리그 전체 조회 기능 구현(대회 관리 페이지)
  • Loading branch information
Zena0128 authored Sep 23, 2024
2 parents 22870d7 + 81dbec7 commit 425f6d2
Show file tree
Hide file tree
Showing 12 changed files with 308 additions and 57 deletions.
6 changes: 5 additions & 1 deletion src/docs/asciidoc/api.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,11 @@ operation::league-team-controller-test/리그팀을_삭제한다[snippets='http-

operation::league-query-controller-test/리그를_하나_조회한다[snippets='http-request,path-parameters,http-response,response-fields']

=== 매니저가 생성한 리그 전체 조회
=== 매니저가 생성한 리그 전체 조회(홈 화면)

operation::league-query-controller-test/매니저가_생성한_모든_리그와_진행중_경기를_조회한다[snippets='http-request,http-response,response-fields']

=== 매니저가 생성한 리그 전체 조회(대회 관리 화면)

operation::league-query-controller-test/매니저가_생성한_모든_리그를_조회한다[snippets='http-request,http-response,response-fields']

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public static Round from(final String value) {
});
}

public static Round fromNumber(int number) {
public static Round from(int number) {
return Stream.of(Round.values())
.filter(round -> round.number == number)
.findAny()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public record Register(
LocalDateTime endAt
) {
public League toEntity(final Member manager) {
return new League(manager, manager.getOrganization(), name, startAt, endAt, Round.fromNumber(maxRound));
return new League(manager, manager.getOrganization(), name, startAt, endAt, Round.from(maxRound));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,15 @@
import com.sports.server.command.member.domain.Member;
import com.sports.server.common.application.EntityUtils;
import com.sports.server.common.exception.NotFoundException;
import com.sports.server.query.dto.response.LeagueDetailResponse;
import com.sports.server.query.dto.response.LeagueResponse;
import com.sports.server.query.dto.response.LeagueResponseWithGames;
import com.sports.server.query.dto.response.LeagueResponseWithInProgressGames;
import com.sports.server.query.dto.response.LeagueSportResponse;
import com.sports.server.query.dto.response.LeagueTeamDetailResponse;
import com.sports.server.query.dto.response.LeagueTeamPlayerResponse;
import com.sports.server.query.dto.response.LeagueTeamResponse;
import com.sports.server.query.dto.response.*;
import com.sports.server.query.repository.GameQueryRepository;
import com.sports.server.query.repository.LeagueQueryRepository;
import com.sports.server.query.repository.LeagueSportQueryRepository;
import com.sports.server.query.repository.LeagueTeamDynamicRepository;
import com.sports.server.query.repository.LeagueTeamPlayerQueryRepository;
import java.time.LocalDateTime;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import lombok.RequiredArgsConstructor;
Expand Down Expand Up @@ -113,4 +108,22 @@ public LeagueResponseWithGames findLeagueAndGames(final Long leagueId) {
List<Game> games = gameQueryRepository.findByLeagueWithGameTeams(league);
return LeagueResponseWithGames.of(league, games);
}

public List<LeagueResponseToManage> findLeaguesByManagerToManage(final Member manager) {
List<League> leagues = leagueQueryRepository.findByManagerToManage(manager);

Comparator<League> comparator = Comparator.comparing(
league -> leagueProgressOrderMap.get(LeagueProgress.getProgressDescription(LocalDateTime.now(), league)));

return leagues.stream()
.sorted(comparator)
.map(LeagueResponseToManage::of)
.toList();
}

public static Map<String, Integer> leagueProgressOrderMap = Map.ofEntries(
Map.entry(LeagueProgress.IN_PROGRESS.getDescription(), 1),
Map.entry(LeagueProgress.BEFORE_START.getDescription(), 2),
Map.entry(LeagueProgress.FINISHED.getDescription(), 3)
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.sports.server.query.dto.response;

import com.sports.server.command.game.domain.Game;
import com.sports.server.command.league.domain.League;
import com.sports.server.command.league.domain.LeagueProgress;

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

public record LeagueResponseToManage(
Long id,
String name,
String leagueProgress,
int sizeOfLeagueTeams,
String maxRound,
LocalDateTime startAt,
LocalDateTime endAt
) {
public static LeagueResponseToManage of(League league) {
return new LeagueResponseToManage(
league.getId(),
league.getName(),
LeagueProgress.getProgressDescription(LocalDateTime.now(), league),
league.getLeagueTeams().size(),
league.getMaxRound().getDescription(),
league.getStartAt(),
league.getEndAt()
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,8 @@

import com.sports.server.command.member.domain.Member;
import com.sports.server.query.application.LeagueQueryService;
import com.sports.server.query.dto.response.LeagueDetailResponse;
import com.sports.server.query.dto.response.LeagueResponse;
import com.sports.server.query.dto.response.LeagueResponseWithGames;
import com.sports.server.query.dto.response.LeagueResponseWithInProgressGames;
import com.sports.server.query.dto.response.LeagueSportResponse;
import com.sports.server.query.dto.response.LeagueTeamDetailResponse;
import com.sports.server.query.dto.response.LeagueTeamPlayerResponse;
import com.sports.server.query.dto.response.LeagueTeamResponse;
import com.sports.server.query.dto.response.*;

import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
Expand Down Expand Up @@ -67,4 +61,9 @@ public ResponseEntity<LeagueTeamDetailResponse> findLeagueTeam(@PathVariable fin
public ResponseEntity<LeagueResponseWithGames> findLeagueAndGames(@PathVariable final Long leagueId) {
return ResponseEntity.ok(leagueQueryService.findLeagueAndGames(leagueId));
}

@GetMapping("/manager/manage")
public ResponseEntity<List<LeagueResponseToManage>> findLeaguesByManagerToManage(final Member manager) {
return ResponseEntity.ok(leagueQueryService.findLeaguesByManagerToManage(manager));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,13 @@ public interface LeagueQueryRepository extends Repository<League, Long>, LeagueQ
)
List<League> findByManager(Member member);

@Query(
"SELECT l FROM League l "
+ "LEFT JOIN FETCH l.leagueTeams "
+ "WHERE l.manager =:member"
)
List<League> findByManagerToManage(Member member);

@Query(
"SELECT l FROM League l "
+ "JOIN FETCH l.leagueTeams "
Expand Down
114 changes: 105 additions & 9 deletions src/main/resources/static/docs/api.html
Original file line number Diff line number Diff line change
Expand Up @@ -495,7 +495,8 @@ <h1>훕치치 서버 API 문서</h1>
<li><a href="#_리그팀_수정">리그팀 수정</a></li>
<li><a href="#_리그팀_삭제">리그팀 삭제</a></li>
<li><a href="#_리그_상세_조회">리그 상세 조회</a></li>
<li><a href="#_매니저가_생성한_리그_전체_조회">매니저가 생성한 리그 전체 조회</a></li>
<li><a href="#_매니저가_생성한_리그_전체_조회홈_화면">매니저가 생성한 리그 전체 조회(홈 화면)</a></li>
<li><a href="#_매니저가_생성한_리그_전체_조회대회_관리_화면">매니저가 생성한 리그 전체 조회(대회 관리 화면)</a></li>
<li><a href="#_리그_삭제">리그 삭제</a></li>
<li><a href="#_리그팀_상세_조회">리그팀 상세 조회</a></li>
<li><a href="#_리그의_정보와_리그에_해당하는_경기_전체_조회">리그의 정보와 리그에 해당하는 경기 전체 조회</a></li>
Expand Down Expand Up @@ -2907,9 +2908,9 @@ <h4 id="_리그_상세_조회_response_fields"><a class="link" href="#_리그_
</div>
</div>
<div class="sect2">
<h3 id="_매니저가_생성한_리그_전체_조회"><a class="link" href="#_매니저가_생성한_리그_전체_조회">매니저가 생성한 리그 전체 조회</a></h3>
<h3 id="_매니저가_생성한_리그_전체_조회홈_화면"><a class="link" href="#_매니저가_생성한_리그_전체_조회홈_화면">매니저가 생성한 리그 전체 조회(홈 화면)</a></h3>
<div class="sect3">
<h4 id="_매니저가_생성한_리그_전체_조회_http_request"><a class="link" href="#_매니저가_생성한_리그_전체_조회_http_request">HTTP request</a></h4>
<h4 id="_매니저가_생성한_리그_전체_조회홈_화면_http_request"><a class="link" href="#_매니저가_생성한_리그_전체_조회홈_화면_http_request">HTTP request</a></h4>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight nowrap"><code class="language-http hljs" data-lang="http">GET /leagues/manager HTTP/1.1
Expand All @@ -2920,19 +2921,15 @@ <h4 id="_매니저가_생성한_리그_전체_조회_http_request"><a class="lin
</div>
</div>
<div class="sect3">
<h4 id="_매니저가_생성한_리그_전체_조회_http_response"><a class="link" href="#_매니저가_생성한_리그_전체_조회_http_response">HTTP response</a></h4>
<h4 id="_매니저가_생성한_리그_전체_조회홈_화면_http_response"><a class="link" href="#_매니저가_생성한_리그_전체_조회홈_화면_http_response">HTTP response</a></h4>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight nowrap"><code class="language-http hljs" data-lang="http">HTTP/1.1 200 OK
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Content-Type: application/json
<<<<<<< HEAD
Content-Length: 629
=======
Content-Length: 633
>>>>>>> 841548f ([DOCS] 문서화 테스트 추가 #215)

[ {
"id" : 1,
Expand Down Expand Up @@ -2963,7 +2960,7 @@ <h4 id="_매니저가_생성한_리그_전체_조회_http_response"><a class="li
</div>
</div>
<div class="sect3">
<h4 id="_매니저가_생성한_리그_전체_조회_response_fields"><a class="link" href="#_매니저가_생성한_리그_전체_조회_response_fields">Response fields</a></h4>
<h4 id="_매니저가_생성한_리그_전체_조회홈_화면_response_fields"><a class="link" href="#_매니저가_생성한_리그_전체_조회홈_화면_response_fields">Response fields</a></h4>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 33.3333%;">
Expand Down Expand Up @@ -3063,6 +3060,105 @@ <h4 id="_매니저가_생성한_리그_전체_조회_response_fields"><a class="
</div>
</div>
<div class="sect2">
<h3 id="_매니저가_생성한_리그_전체_조회대회_관리_화면"><a class="link" href="#_매니저가_생성한_리그_전체_조회대회_관리_화면">매니저가 생성한 리그 전체 조회(대회 관리 화면)</a></h3>
<div class="sect3">
<h4 id="_매니저가_생성한_리그_전체_조회대회_관리_화면_http_request"><a class="link" href="#_매니저가_생성한_리그_전체_조회대회_관리_화면_http_request">HTTP request</a></h4>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight nowrap"><code class="language-http hljs" data-lang="http">GET /leagues/manager/manage HTTP/1.1
Content-Type: application/json
Host: www.api.hufstreaming.site
Cookie: HCC_SES=temp-cookie</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_매니저가_생성한_리그_전체_조회대회_관리_화면_http_response"><a class="link" href="#_매니저가_생성한_리그_전체_조회대회_관리_화면_http_response">HTTP response</a></h4>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight nowrap"><code class="language-http hljs" data-lang="http">HTTP/1.1 200 OK
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Content-Type: application/json
Content-Length: 437

[ {
"id" : 1,
"name" : "삼건물 대회",
"leagueProgress" : "진행 중",
"sizeOfLeagueTeams" : 2,
"maxRound" : "16강",
"startAt" : "2024-09-19T22:48:29.959422",
"endAt" : "2024-09-19T22:48:29.959426"
}, {
"id" : 2,
"name" : "탁구 대회",
"leagueProgress" : "시작 전",
"sizeOfLeagueTeams" : 2,
"maxRound" : "16강",
"startAt" : "2024-09-19T22:48:29.959436",
"endAt" : "2024-09-19T22:48:29.959436"
} ]</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_매니저가_생성한_리그_전체_조회대회_관리_화면_response_fields"><a class="link" href="#_매니저가_생성한_리그_전체_조회대회_관리_화면_response_fields">Response fields</a></h4>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 33.3333%;">
<col style="width: 33.3333%;">
<col style="width: 33.3334%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Path</th>
<th class="tableblock halign-left valign-top">Type</th>
<th class="tableblock halign-left valign-top">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>[].id</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>[].leagueProgress</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">리그의 진행 상태 ex. 진행 중, 종료</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>[].sizeOfLeagueTeams</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">리그 팀의 수</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>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>
<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>[].endAt</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>
</tbody>
</table>
</div>
</div>
<div class="sect2">
<h3 id="_리그_삭제"><a class="link" href="#_리그_삭제">리그 삭제</a></h3>
<div class="sect3">
<h4 id="_리그_삭제_http_request"><a class="link" href="#_리그_삭제_http_request">HTTP request</a></h4>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,10 @@

import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertAll;
import static org.junit.jupiter.api.Assertions.assertTimeout;

import com.sports.server.command.league.domain.LeagueProgress;
import com.sports.server.query.dto.response.LeagueDetailResponse;
import com.sports.server.query.dto.response.LeagueResponse;
import com.sports.server.query.dto.response.LeagueSportResponse;
import com.sports.server.query.dto.response.LeagueTeamDetailResponse;
import com.sports.server.query.dto.response.LeagueTeamPlayerResponse;
import com.sports.server.query.dto.response.*;
import com.sports.server.support.AcceptanceTest;
import io.restassured.RestAssured;
import io.restassured.response.ExtractableResponse;
Expand Down Expand Up @@ -39,16 +36,16 @@ public class LeagueQueryAcceptanceTest extends AcceptanceTest {
() -> assertThat(response.statusCode()).isEqualTo(HttpStatus.OK.value()),
() -> assertThat(actual)
.map(LeagueResponse::leagueId)
.containsExactly(8L, 3L, 2L, 1L, 7L, 6L, 5L),
.containsExactly(10L, 8L, 9L, 3L, 2L, 1L, 7L, 6L, 5L),
() -> assertThat(actual)
.map(LeagueResponse::name)
.containsExactly("탁구 대회", "롤 대회", "농구대잔치", "삼건물 대회", "롤 대회", "농구대잔치", "삼건물 대회"),
.containsExactly("축구 대회", "탁구 대회", "야구 대회", "롤 대회", "농구대잔치", "삼건물 대회", "롤 대회", "농구대잔치", "삼건물 대회"),
() -> assertThat(actual)
.map(LeagueResponse::maxRound)
.containsExactly("16강", "8강", "8강", "16강", "8강", "8강", "16강"),
.containsExactly("16강", "16강", "16강", "8강", "8강", "16강", "8강", "8강", "16강"),
() -> assertThat(actual)
.map(LeagueResponse::inProgressRound)
.containsExactly("16강", "8강", "결승", "8강", "8강", "결승", "8강")
.containsExactly("16강", "16강", "16강", "8강", "결승", "8강", "8강", "결승", "8강")
);
}

Expand Down Expand Up @@ -149,7 +146,7 @@ public class LeagueQueryAcceptanceTest extends AcceptanceTest {
}

@Test
void 매니저가_생성한_리그를_모두_조회한다() {
void 매니저가_생성한_리그를_진행_중인_경기와_함께_모두_조회한다() {

// given
configureMockJwtForEmail("[email protected]");
Expand All @@ -166,6 +163,33 @@ public class LeagueQueryAcceptanceTest extends AcceptanceTest {
assertThat(response.statusCode()).isEqualTo(HttpStatus.OK.value());
}

@Test
void 매니저가_생성한_리그를_모두_조회한다() {

// given
configureMockJwtForEmail("[email protected]");

// when
ExtractableResponse<Response> response = RestAssured.given().log().all()
.cookie(COOKIE_NAME, mockToken)
.contentType(MediaType.APPLICATION_JSON_VALUE)
.get("/leagues/manager/manage")
.then().log().all()
.extract();

// then
List<LeagueResponseToManage> actual = toResponses(response, LeagueResponseToManage.class);
assertAll(
() -> assertThat(response.statusCode()).isEqualTo(HttpStatus.OK.value()),
() -> assertThat(actual.size()).isEqualTo(8),
() -> assertThat(actual.get(0).name()).isEqualTo("야구 대회"),
() -> assertThat(actual.get(0).leagueProgress()).isEqualTo(LeagueProgress.IN_PROGRESS.getDescription()),
() -> assertThat(actual.get(1).leagueProgress()).isEqualTo(LeagueProgress.BEFORE_START.getDescription()),
() -> assertThat(actual.get(0).sizeOfLeagueTeams()).isEqualTo(2)
);

}

@Test
void 리그팀의_상세정보를_조회한다() {
// given
Expand Down
Loading

0 comments on commit 425f6d2

Please sign in to comment.