Skip to content

Commit

Permalink
Merge pull request #42 from Nexters/dev
Browse files Browse the repository at this point in the history
Dev -> Main 08.17
  • Loading branch information
parkdaye authored Aug 17, 2023
2 parents 070c7a7 + 9473de4 commit 6e06182
Show file tree
Hide file tree
Showing 14 changed files with 251 additions and 211 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public enum ExceptionInfo {
COMPLETED_TEAM_BUILDING("이미 종료된 팀빌딩입니다.", HttpStatus.BAD_REQUEST),
INVALID_ADJUST_REQUEST("조정 라운드에서만 조정 가능합니다.", HttpStatus.BAD_REQUEST),
INVALID_FINISH_REQUEST("조정 라운드에서만 팀빌딩을 종료할 수 있습니다.", HttpStatus.BAD_REQUEST),
;
DUPLICATED_PICK_REQUEST("이미 선택이 완료된 팀입니다.", HttpStatus.BAD_REQUEST);
@Getter
private final String message;
private final HttpStatus status;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import com.nexters.moyeomoyeo.team_building.controller.dto.request.UserAdjustRequest;
import com.nexters.moyeomoyeo.team_building.controller.dto.response.TeamBuildingResponse;
import com.nexters.moyeomoyeo.team_building.controller.dto.response.UserInfo;
import com.nexters.moyeomoyeo.team_building.service.TeamBuildingService;
import com.nexters.moyeomoyeo.team_building.service.TeamBuildingAdminService;
import com.nexters.moyeomoyeo.team_building.service.UserService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Content;
Expand All @@ -29,7 +29,7 @@
@Tag(name = "어드민", description = "어드민 관련 팀빌딩 api 입니다.")
public class TeamBuildingAdminController {

private final TeamBuildingService teamBuildingService;
private final TeamBuildingAdminService adminService;
private final UserService userService;

@Operation(summary = "팀 빌딩 생성 요청", description = "팀빌딩 방과 팀 리스트를 생성됩니다. ")
Expand All @@ -39,7 +39,7 @@ public class TeamBuildingAdminController {
@PostMapping
public ResponseEntity<TeamBuildingResponse> createTeamBuilding(
@RequestBody @Valid TeamBuildingRequest teamBuildingRequest) {
return ResponseEntity.ok(teamBuildingService.createTeamBuilding(teamBuildingRequest));
return ResponseEntity.ok(adminService.createTeamBuilding(teamBuildingRequest));
}

@Operation(summary = "팀원 조정 (단일 유저) ", description = """
Expand All @@ -49,8 +49,7 @@ public ResponseEntity<TeamBuildingResponse> createTeamBuilding(
@PostMapping("/{teamBuildingUuid}/users/{userUuid}")
public ResponseEntity<UserInfo> adjustUser(@PathVariable(value = "teamBuildingUuid") String teamBuildingUuid,
@PathVariable(value = "userUuid") String userUuid, @RequestBody @Valid UserAdjustRequest userAdjustRequest) {
return ResponseEntity.ok(
teamBuildingService.adjustUser(teamBuildingUuid, userUuid, userAdjustRequest.getTeamUuid()));
return ResponseEntity.ok(adminService.adjustUser(teamBuildingUuid, userUuid, userAdjustRequest.getTeamUuid()));
}

@Operation(summary = "팀원 삭제 (단일 유저) ", description = """
Expand All @@ -70,7 +69,7 @@ public ResponseEntity<Void> deleteUser(@PathVariable(value = "teamBuildingUuid")
""")
@PutMapping("/{teamBuildingUuid}/finish")
public ResponseEntity<Void> finishTeamBuilding(@PathVariable(value = "teamBuildingUuid") String teamBuildingUuid) {
teamBuildingService.finishTeamBuilding(teamBuildingUuid);
adminService.finishTeamBuilding(teamBuildingUuid);
return ResponseEntity.ok().build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import com.nexters.moyeomoyeo.team_building.controller.dto.request.UserPickRequest;
import com.nexters.moyeomoyeo.team_building.controller.dto.response.TeamBuildingResponse;
import com.nexters.moyeomoyeo.team_building.controller.dto.response.UserPickResponse;
import com.nexters.moyeomoyeo.team_building.service.TeamBuildingService;
import com.nexters.moyeomoyeo.team_building.service.TeamBuildingCoreService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
Expand All @@ -26,8 +26,7 @@
@RequiredArgsConstructor
public class TeamBuildingController {

private final TeamBuildingService teamBuildingService;

private final TeamBuildingCoreService coreService;

@Operation(summary = "팀 빌딩 현황 조회", description = "팀빌딩 현황 데이터가 조회됩니다. ")
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = TeamBuildingResponse.class)))
Expand All @@ -36,7 +35,7 @@ public class TeamBuildingController {
@GetMapping("/{teamBuildingUuid}")
public ResponseEntity<TeamBuildingResponse> findTeamBuilding(
@PathVariable(value = "teamBuildingUuid") String teamBuildingUuid) {
return ResponseEntity.ok(teamBuildingService.findTeamBuilding(teamBuildingUuid));
return ResponseEntity.ok(coreService.findTeamBuilding(teamBuildingUuid));
}


Expand All @@ -52,7 +51,7 @@ public ResponseEntity<UserPickResponse> pickUsers(
@PathVariable(value = "teamBuildingUuid") String teamBuildingUuid,
@PathVariable(value = "teamUuid") String teamUuid,
@RequestBody @Valid UserPickRequest userPickRequest) {
return ResponseEntity.ok(teamBuildingService.pickUsers(teamBuildingUuid, teamUuid, userPickRequest));
return ResponseEntity.ok(coreService.pickUsers(teamBuildingUuid, teamUuid, userPickRequest));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,13 @@ public class TeamBuilding extends BaseEntity {
@Builder.Default
private List<Team> teams = new ArrayList<>();

public void nextRound() {
public RoundStatus nextRound() {
if (this.roundStatus == RoundStatus.COMPLETE) {
throw ExceptionInfo.COMPLETED_TEAM_BUILDING.exception();
}

this.roundStatus = this.roundStatus.getNextStatus();
return this.roundStatus;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public class User extends BaseEntity {
@JoinColumn(name = "team_id")
private Team team;

private Long teamBuildingId;
private String teamBuildingUuid;

public void addTeam(Team team) {
if (this.team != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,5 @@ public interface UserRepository {

List<User> findByUuidIn(List<String> uuids);

List<User> findByTeamBuildingId(Long teamBuildingId);
List<User> findByTeamBuildingUuid(String teamBuildingUuid);
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,5 @@ public interface UserJpa extends JpaRepository<User, Long> {

List<User> findByUuidIn(List<String> uuids);

List<User> findByTeamBuildingId(Long teamBuildingId);
List<User> findByTeamBuildingUuid(String teamBuildingUuid);
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public List<User> findByUuidIn(List<String> uuids) {
}

@Override
public List<User> findByTeamBuildingId(Long teamBuildingId) {
return jpa.findByTeamBuildingId(teamBuildingId);
public List<User> findByTeamBuildingUuid(String teamBuildingUuid) {
return jpa.findByTeamBuildingUuid(teamBuildingUuid);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package com.nexters.moyeomoyeo.team_building.service;


import static com.nexters.moyeomoyeo.team_building.controller.dto.response.TeamBuildingResponse.TeamBuildingInfo.makeTeamBuildingInfo;
import static com.nexters.moyeomoyeo.team_building.controller.dto.response.UserInfo.makeUserInfo;

import com.nexters.moyeomoyeo.common.constant.ExceptionInfo;
import com.nexters.moyeomoyeo.notification.service.NotificationService;
import com.nexters.moyeomoyeo.team_building.controller.dto.request.TeamBuildingRequest;
import com.nexters.moyeomoyeo.team_building.controller.dto.request.TeamRequest;
import com.nexters.moyeomoyeo.team_building.controller.dto.response.TeamBuildingResponse;
import com.nexters.moyeomoyeo.team_building.controller.dto.response.TeamInfo;
import com.nexters.moyeomoyeo.team_building.controller.dto.response.UserInfo;
import com.nexters.moyeomoyeo.team_building.domain.constant.RoundStatus;
import com.nexters.moyeomoyeo.team_building.domain.entity.Team;
import com.nexters.moyeomoyeo.team_building.domain.entity.TeamBuilding;
import com.nexters.moyeomoyeo.team_building.domain.entity.User;
import java.util.List;
import java.util.Objects;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@RequiredArgsConstructor
public class TeamBuildingAdminService {

private final TeamBuildingService teamBuildingService;
private final UserService userService;
private final NotificationService notificationService;

@Transactional
public UserInfo adjustUser(String teamBuildingUuid, String userUuid, String teamUuid) {
final TeamBuilding teamBuilding = teamBuildingService.findByUuid(teamBuildingUuid);

if (RoundStatus.ADJUSTED_ROUND != teamBuilding.getRoundStatus()) {
throw ExceptionInfo.INVALID_ADJUST_REQUEST.exception();
}

final User user = userService.findByUuid(userUuid);
final Team targetTeam = teamBuilding.getTeams()
.stream()
.filter(team -> Objects.equals(team.getUuid(), teamUuid))
.findFirst()
.orElse(null);
user.adjustTeam(targetTeam);
UserInfo userInfo = makeUserInfo(user);

notificationService.broadCast(teamBuildingUuid, "adjust-user", userInfo);
return userInfo;
}


@Transactional
public void finishTeamBuilding(String uuid) {
final TeamBuilding teamBuilding = teamBuildingService.findByUuid(uuid);

if (RoundStatus.ADJUSTED_ROUND != teamBuilding.getRoundStatus()) {
throw ExceptionInfo.INVALID_FINISH_REQUEST.exception();
}

teamBuilding.nextRound();
notificationService.broadCast(teamBuilding.getUuid(), "finish-team-building", teamBuilding.getRoundStatus());
}


@Transactional
public TeamBuildingResponse createTeamBuilding(TeamBuildingRequest teamBuildingRequest) {
final TeamBuilding teamBuilding = TeamBuilding.builder()
.name(teamBuildingRequest.getName())
.build();

final List<Team> teams = teamBuildingRequest.getTeams()
.stream()
.map(TeamRequest::toEntity)
.toList();

for (final Team team : teams) {
team.addTeamBuilding(teamBuilding);
}

final TeamBuilding savedTeamBuilding = teamBuildingService.save(teamBuilding);

return TeamBuildingResponse.builder()
.teamBuildingInfo(makeTeamBuildingInfo(savedTeamBuilding))
.teamInfoList(savedTeamBuilding.getTeams().stream().map(TeamInfo::makeTeamInfo).toList())
.build();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
package com.nexters.moyeomoyeo.team_building.service;

import static com.nexters.moyeomoyeo.team_building.controller.dto.response.TeamBuildingResponse.TeamBuildingInfo.makeTeamBuildingInfo;
import static com.nexters.moyeomoyeo.team_building.controller.dto.response.TeamInfo.isSelectDone;

import com.nexters.moyeomoyeo.common.constant.ExceptionInfo;
import com.nexters.moyeomoyeo.notification.service.NotificationService;
import com.nexters.moyeomoyeo.team_building.controller.dto.request.UserPickRequest;
import com.nexters.moyeomoyeo.team_building.controller.dto.response.PickUserResponse;
import com.nexters.moyeomoyeo.team_building.controller.dto.response.TeamBuildingResponse;
import com.nexters.moyeomoyeo.team_building.controller.dto.response.TeamInfo;
import com.nexters.moyeomoyeo.team_building.controller.dto.response.UserInfo;
import com.nexters.moyeomoyeo.team_building.controller.dto.response.UserPickResponse;
import com.nexters.moyeomoyeo.team_building.domain.constant.RoundStatus;
import com.nexters.moyeomoyeo.team_building.domain.entity.Team;
import com.nexters.moyeomoyeo.team_building.domain.entity.TeamBuilding;
import com.nexters.moyeomoyeo.team_building.domain.entity.User;
import com.nexters.moyeomoyeo.team_building.domain.entity.UserChoice;
import java.util.List;
import java.util.Objects;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@RequiredArgsConstructor
public class TeamBuildingCoreService {

private final TeamBuildingService teamBuildingService;
private final UserService userService;
private final NotificationService notificationService;

/**
* 선택된 유저가 현재 라운드에서 지망한 팀이 유저를 선택한 팀과 일치하는지 유효성 체크.
*
* @param team 유저를 선택한 팀
* @param pickedUsers 선택된 유저 목록
* @return 일치여부
*/
private static boolean isChosenTeam(Team team, List<User> pickedUsers) {
final RoundStatus roundStatus = team.getRoundStatus();
for (final User user : pickedUsers) {
final UserChoice choice = user.findChoice(roundStatus.getWeight());
if (!Objects.equals(choice.getTeamUuid(), team.getUuid())) {
return false;
}
}

return true;
}

/**
* 모든 팀이 선택을 완료했는지 판단.
*
* @param teams team building 의 team 들
* @param roundStatus 전체 round 상태
* @return 완료됐으면 true
*/
private static boolean isAllTeamSelected(List<Team> teams, RoundStatus roundStatus) {
for (final Team team : teams) {
if (roundStatus == team.getRoundStatus()) {
return false;
}
}

return true;
}

@Transactional(readOnly = true)
public TeamBuildingResponse findTeamBuilding(String teamBuildingUuid) {
final TeamBuilding teamBuilding = teamBuildingService.findByUuid(teamBuildingUuid);

final List<User> users = userService.findByTeamBuildingId(teamBuildingUuid);

return TeamBuildingResponse.builder()
.teamBuildingInfo(makeTeamBuildingInfo(teamBuilding))
.teamInfoList(teamBuilding.getTeams().stream().map(TeamInfo::makeTeamInfo).toList())
.userInfoList(users.stream().map(UserInfo::makeUserInfo).toList())
.build();
}

@Transactional
public UserPickResponse pickUsers(String teamBuildingUuid, String teamUuid, UserPickRequest userPickRequest) {
final TeamBuilding teamBuilding = teamBuildingService.findByUuid(teamBuildingUuid);
final RoundStatus teamBuildingRoundStatus = teamBuilding.getRoundStatus();

if (RoundStatus.COMPLETE == teamBuildingRoundStatus) {
throw ExceptionInfo.COMPLETED_TEAM_BUILDING.exception();
}

final Team targetTeam = teamBuilding.getTeams()
.stream()
.filter(team -> teamUuid.equals(team.getUuid()))
.findFirst()
.orElseThrow(ExceptionInfo.INVALID_TEAM_UUID::exception);

if (isSelectDone(teamBuildingRoundStatus, targetTeam.getRoundStatus())) {
throw ExceptionInfo.DUPLICATED_PICK_REQUEST.exception();
}

final List<String> userUuids = userPickRequest.getUserUuids();
final List<User> pickedUsers = userService.findByUuidIn(userUuids);

if (!isChosenTeam(targetTeam, pickedUsers)) {
throw ExceptionInfo.BAD_REQUEST_FOR_USER_PICK.exception();
}

for (final User user : pickedUsers) {
user.addTeam(targetTeam);
}
targetTeam.nextRound();

PickUserResponse userResponse = PickUserResponse.builder()
.teamName(targetTeam.getName())
.teamUuid(teamUuid)
.pickUserUuids(userUuids)
.build();

notificationService.broadCast(teamBuilding.getUuid(), "pick-user", userResponse);

if (isAllTeamSelected(teamBuilding.getTeams(), teamBuildingRoundStatus)) {
final RoundStatus nextStatus = teamBuilding.nextRound();
notificationService.broadCast(teamBuilding.getUuid(), "change-round", nextStatus);
}

return UserPickResponse.builder()
.userInfoList(targetTeam.getUsers().stream().map(UserInfo::makeUserInfo).toList())
.build();
}
}
Loading

0 comments on commit 6e06182

Please sign in to comment.