diff --git a/build.gradle b/build.gradle index dfa2b9b..fb995bf 100644 --- a/build.gradle +++ b/build.gradle @@ -1,7 +1,7 @@ plugins { id 'java' - id 'org.springframework.boot' version '3.0.6' - id 'io.spring.dependency-management' version '1.1.0' + id 'org.springframework.boot' version '3.2.6' + id 'io.spring.dependency-management' version '1.1.5' } group = 'com.nexters' @@ -25,6 +25,7 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework.boot:spring-boot-starter-validation' + implementation 'io.hypersistence:hypersistence-utils-hibernate-63:3.7.7' compileOnly 'org.projectlombok:lombok' runtimeOnly 'com.h2database:h2' runtimeOnly 'com.mysql:mysql-connector-j' @@ -33,11 +34,11 @@ dependencies { // Micrometer 의존성 추가 implementation 'io.micrometer:micrometer-core:1.10.8' implementation 'io.micrometer:micrometer-registry-prometheus:1.10.8' + testImplementation 'io.micrometer:micrometer-observation:1.10.8' implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.0.2' testImplementation 'org.springframework.boot:spring-boot-starter-test' - testImplementation 'io.micrometer:micrometer-observation:1.10.8' implementation 'com.google.code.findbugs:jsr305:3.0.2' diff --git a/src/main/java/com/nexters/moyeomoyeo/common/constant/ExceptionInfo.java b/src/main/java/com/nexters/moyeomoyeo/common/constant/ExceptionInfo.java index 5d1ce79..f58823b 100644 --- a/src/main/java/com/nexters/moyeomoyeo/common/constant/ExceptionInfo.java +++ b/src/main/java/com/nexters/moyeomoyeo/common/constant/ExceptionInfo.java @@ -11,9 +11,10 @@ public enum ExceptionInfo { INVALID_TEAM_BUILDING_UUID("팀빌딩을 찾을 수 없습니다.", HttpStatus.BAD_REQUEST), INVALID_TEAM_UUID("팀을 찾을 수 없습니다.", HttpStatus.BAD_REQUEST), INVALID_USER_UUID("유저를 찾을 수 없습니다.", HttpStatus.BAD_REQUEST), - BAD_REQUEST_FOR_USER_PICK("해당 유저를 선택할 수 없습니다.", HttpStatus.BAD_REQUEST), + BAD_REQUEST_FOR_USER_PICK("유효하지 않은 유저 선택 요청입니다.", HttpStatus.BAD_REQUEST), ALREADY_JOINED_USER("다른 팀에 배정되어 있는 유저입니다.", HttpStatus.BAD_REQUEST), COMPLETED_TEAM_BUILDING("이미 종료된 팀빌딩입니다.", HttpStatus.BAD_REQUEST), + INVALID_START_REQUEST("시작 라운드에서만 팀빌딩을 시작할 수 있습니다.", HttpStatus.BAD_REQUEST), INVALID_ADJUST_REQUEST("조정 라운드에서만 조정 가능합니다.", HttpStatus.BAD_REQUEST), INVALID_FINISH_REQUEST("조정 라운드에서만 팀빌딩을 종료할 수 있습니다.", HttpStatus.BAD_REQUEST), INVALID_DELETE_REQUEST("1라운드에서만 회원을 삭제할 수 있습니다.", HttpStatus.BAD_REQUEST), diff --git a/src/main/java/com/nexters/moyeomoyeo/notification/service/NotificationService.java b/src/main/java/com/nexters/moyeomoyeo/notification/service/NotificationService.java index 6206c63..fef5330 100644 --- a/src/main/java/com/nexters/moyeomoyeo/notification/service/NotificationService.java +++ b/src/main/java/com/nexters/moyeomoyeo/notification/service/NotificationService.java @@ -33,7 +33,7 @@ public SseEmitter subscribe(String teamBuildingUuid) { return emitter; } - public void broadCast(String teamBuildingUuid, String name, Object data) { + public void broadcast(String teamBuildingUuid, String name, Object data) { for (final SseEmitter emitter : handler.getEmitters(teamBuildingUuid)) { sendNotification(emitter, name, data); } diff --git a/src/main/java/com/nexters/moyeomoyeo/team_building/controller/TeamBuildingAdminController.java b/src/main/java/com/nexters/moyeomoyeo/team_building/controller/TeamBuildingAdminController.java index d54e8b3..aa06c72 100644 --- a/src/main/java/com/nexters/moyeomoyeo/team_building/controller/TeamBuildingAdminController.java +++ b/src/main/java/com/nexters/moyeomoyeo/team_building/controller/TeamBuildingAdminController.java @@ -30,7 +30,6 @@ public class TeamBuildingAdminController { private final TeamBuildingAdminService adminService; - private final UserService userService; @Operation(summary = "팀 빌딩 생성 요청", description = "팀빌딩 방과 팀 리스트를 생성됩니다. ") @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = TeamBuildingResponse.class))) @@ -78,4 +77,16 @@ public ResponseEntity finishTeamBuilding(@PathVariable(value = "teamBuildi .header("X-Accel-Buffering", "no") .build(); } + + @Operation(summary = "팀 빌딩 시작하기", description = """ + 운영진이 START 단계에서 팀빌딩을 시작합니다. \s + event : start-team-building, data : RoundStatus(FIRST_ROUND) \s + """) + @PutMapping("/{teamBuildingUuid}/start") + public ResponseEntity startTeamBuilding(@PathVariable(value = "teamBuildingUuid") String teamBuildingUuid) { + adminService.startTeamBuilding(teamBuildingUuid); + return ResponseEntity.ok() + .header("X-Accel-Buffering", "no") + .build(); + } } diff --git a/src/main/java/com/nexters/moyeomoyeo/team_building/controller/UserSurveyController.java b/src/main/java/com/nexters/moyeomoyeo/team_building/controller/UserSurveyController.java index 1f83119..fe5cf62 100644 --- a/src/main/java/com/nexters/moyeomoyeo/team_building/controller/UserSurveyController.java +++ b/src/main/java/com/nexters/moyeomoyeo/team_building/controller/UserSurveyController.java @@ -5,7 +5,7 @@ import com.nexters.moyeomoyeo.team_building.controller.dto.request.UserRequest; 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.TeamBuildingCoreService; import com.nexters.moyeomoyeo.team_building.service.UserService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; @@ -15,12 +15,7 @@ import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; @RestController @Tag(name = "유저 설문", description = "유저 설문 페이지 관련 api 입니다.") @@ -29,7 +24,7 @@ public class UserSurveyController { private final UserService userService; - private final TeamBuildingService teamBuildingService; + private final TeamBuildingCoreService teamBuildingCoreService; @Operation(summary = "회원 생성 요청", description = """ 회원이 생성됩니다. \s @@ -39,7 +34,7 @@ public class UserSurveyController { @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionResponse.class))}) @PostMapping("/{teamBuildingUuid}/users") public ResponseEntity createUser(@PathVariable(value = "teamBuildingUuid") String teamBuildingUuid, - @RequestBody @Valid UserRequest userRequest) { + @RequestBody @Valid UserRequest userRequest) { return ResponseEntity.ok() .header("X-Accel-Buffering", "no") .body(userService.createUser(teamBuildingUuid, userRequest)); @@ -47,8 +42,8 @@ public ResponseEntity createUser(@PathVariable(value = "teamBuildingUu @Operation(summary = "팀 빌딩 팀 데이터 조회", description = "팀 빌딩, 팀 정보가 조회됩니다. (유저 선택 정보 제외) ") @GetMapping("/{teamBuildingUuid}/teams") - public ResponseEntity findTeamBuildingAndTeams( + public ResponseEntity findTeamBuildingExcludingUser( @PathVariable(value = "teamBuildingUuid") String teamBuildingUuid) { - return ResponseEntity.ok(teamBuildingService.findTeamBuildingAndTeams(teamBuildingUuid)); + return ResponseEntity.ok(teamBuildingCoreService.findTeamBuildingExcludingUser(teamBuildingUuid)); } } diff --git a/src/main/java/com/nexters/moyeomoyeo/team_building/controller/dto/response/UserInfo.java b/src/main/java/com/nexters/moyeomoyeo/team_building/controller/dto/response/UserInfo.java index 78dd75b..663a70d 100644 --- a/src/main/java/com/nexters/moyeomoyeo/team_building/controller/dto/response/UserInfo.java +++ b/src/main/java/com/nexters/moyeomoyeo/team_building/controller/dto/response/UserInfo.java @@ -3,8 +3,8 @@ import com.nexters.moyeomoyeo.team_building.domain.constant.Position; import com.nexters.moyeomoyeo.team_building.domain.constant.RoundStatus; import com.nexters.moyeomoyeo.team_building.domain.entity.User; -import com.nexters.moyeomoyeo.team_building.domain.entity.UserChoice; import io.swagger.v3.oas.annotations.media.Schema; +import java.time.LocalDateTime; import java.util.List; import java.util.Objects; import lombok.AccessLevel; @@ -33,23 +33,21 @@ public class UserInfo { private String profileLink; @Schema(description = "선택받은 라운드") private RoundStatus selectedRound; + private LocalDateTime createdDate; public static UserInfo makeUserInfo(User user) { - final List choices = user.getChoices().stream() - .map(UserChoice::getTeamUuid) - .toList(); - final String joinedTeamUuid = Objects.isNull(user.getTeam()) ? null : user.getTeam().getUuid(); return UserInfo.builder() .uuid(user.getUuid()) .userName(user.getName()) .position(user.getPosition()) - .choices(choices) + .choices(user.getChoices()) .joinedTeamUuid(joinedTeamUuid) .profileLink(user.getProfileLink()) .selectedRound(user.getSelectedRound()) + .createdDate(user.getCreatedDate()) .build(); } } diff --git a/src/main/java/com/nexters/moyeomoyeo/team_building/domain/constant/RoundStatus.java b/src/main/java/com/nexters/moyeomoyeo/team_building/domain/constant/RoundStatus.java index 6b7ef81..5b76344 100644 --- a/src/main/java/com/nexters/moyeomoyeo/team_building/domain/constant/RoundStatus.java +++ b/src/main/java/com/nexters/moyeomoyeo/team_building/domain/constant/RoundStatus.java @@ -1,24 +1,30 @@ package com.nexters.moyeomoyeo.team_building.domain.constant; +import java.util.List; import lombok.Getter; public enum RoundStatus { COMPLETE(6, null), ADJUSTED_ROUND(5, COMPLETE), - FORTH_ROUND(4, ADJUSTED_ROUND), - THIRD_ROUND(3, FORTH_ROUND), + FOURTH_ROUND(4, ADJUSTED_ROUND), + THIRD_ROUND(3, FOURTH_ROUND), SECOND_ROUND(2, THIRD_ROUND), FIRST_ROUND(1, SECOND_ROUND), + START(0, FIRST_ROUND) ; @Getter - final private int weight; + private final int order; @Getter - final private RoundStatus nextStatus; + private final RoundStatus nextStatus; - RoundStatus(int weight, RoundStatus nextStatus) { - this.weight = weight; + RoundStatus(int order, RoundStatus nextStatus) { + this.order = order; this.nextStatus = nextStatus; } + + public static boolean isPickUserPossible(RoundStatus roundStatus) { + return List.of(FIRST_ROUND, SECOND_ROUND, THIRD_ROUND, FOURTH_ROUND).contains(roundStatus); + } } diff --git a/src/main/java/com/nexters/moyeomoyeo/team_building/domain/entity/Team.java b/src/main/java/com/nexters/moyeomoyeo/team_building/domain/entity/Team.java index 7f7ade2..9373072 100644 --- a/src/main/java/com/nexters/moyeomoyeo/team_building/domain/entity/Team.java +++ b/src/main/java/com/nexters/moyeomoyeo/team_building/domain/entity/Team.java @@ -47,7 +47,7 @@ public class Team extends BaseEntity { @Enumerated(EnumType.STRING) @Column(name = "round_status") @Builder.Default - private RoundStatus roundStatus = RoundStatus.FIRST_ROUND; + private RoundStatus roundStatus = RoundStatus.START; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "team_building_id") @@ -57,16 +57,6 @@ public class Team extends BaseEntity { @Builder.Default private List users = new ArrayList<>(); - protected Team(String name, String pmName, Position pmPosition, RoundStatus roundStatus, - TeamBuilding teamBuilding) { - this.name = name; - this.pmName = pmName; - this.pmPosition = pmPosition; - this.uuid = UuidGenerator.createUuid(); - this.roundStatus = roundStatus; - this.teamBuilding = teamBuilding; - } - public void nextRound() { if (this.roundStatus == RoundStatus.COMPLETE) { throw ExceptionInfo.COMPLETED_TEAM_BUILDING.exception(); @@ -77,6 +67,5 @@ public void nextRound() { public void addTeamBuilding(TeamBuilding teamBuilding) { this.teamBuilding = teamBuilding; - this.teamBuilding.getTeams().add(this); } } diff --git a/src/main/java/com/nexters/moyeomoyeo/team_building/domain/entity/TeamBuilding.java b/src/main/java/com/nexters/moyeomoyeo/team_building/domain/entity/TeamBuilding.java index e9112e1..f5f06e1 100644 --- a/src/main/java/com/nexters/moyeomoyeo/team_building/domain/entity/TeamBuilding.java +++ b/src/main/java/com/nexters/moyeomoyeo/team_building/domain/entity/TeamBuilding.java @@ -2,6 +2,7 @@ import static com.nexters.moyeomoyeo.team_building.domain.constant.RoundStatus.FIRST_ROUND; +import static com.nexters.moyeomoyeo.team_building.domain.constant.RoundStatus.START; import com.nexters.moyeomoyeo.common.constant.ExceptionInfo; import com.nexters.moyeomoyeo.common.entity.BaseEntity; @@ -43,7 +44,7 @@ public class TeamBuilding extends BaseEntity { @Enumerated(EnumType.STRING) @Column(name = "round_status") @Builder.Default - private RoundStatus roundStatus = FIRST_ROUND; + private RoundStatus roundStatus = START; @OneToMany(mappedBy = "teamBuilding", cascade = CascadeType.ALL) @Builder.Default diff --git a/src/main/java/com/nexters/moyeomoyeo/team_building/domain/entity/User.java b/src/main/java/com/nexters/moyeomoyeo/team_building/domain/entity/User.java index 904d86c..46606bd 100644 --- a/src/main/java/com/nexters/moyeomoyeo/team_building/domain/entity/User.java +++ b/src/main/java/com/nexters/moyeomoyeo/team_building/domain/entity/User.java @@ -5,6 +5,7 @@ import com.nexters.moyeomoyeo.common.util.UuidGenerator; import com.nexters.moyeomoyeo.team_building.domain.constant.Position; import com.nexters.moyeomoyeo.team_building.domain.constant.RoundStatus; +import io.hypersistence.utils.hibernate.type.json.JsonType; import io.micrometer.common.lang.Nullable; import jakarta.persistence.CascadeType; import jakarta.persistence.Column; @@ -26,6 +27,7 @@ import lombok.Getter; import lombok.NoArgsConstructor; import lombok.experimental.SuperBuilder; +import org.hibernate.annotations.Type; @Entity @Getter @@ -50,10 +52,10 @@ public class User extends BaseEntity { private String profileLink; - @OneToMany(mappedBy = "user", cascade = CascadeType.ALL, fetch = FetchType.LAZY) - @OrderBy("choice_order asc") + @Type(JsonType.class) + @Column(columnDefinition = "TEXT") @Builder.Default - private List choices = new ArrayList<>(); + private List choices = new ArrayList<>(); @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "team_id") @@ -73,8 +75,12 @@ public void addTeam(Team team) { } - public UserChoice findChoice(int weight) { - return this.choices.get(weight - 1); + /** + * @param order 순서 + * @return 순서에 해당하는 teamUuid + */ + public String findChoice(int order) { + return this.choices.get(order - 1); } diff --git a/src/main/java/com/nexters/moyeomoyeo/team_building/domain/entity/UserChoice.java b/src/main/java/com/nexters/moyeomoyeo/team_building/domain/entity/UserChoice.java deleted file mode 100644 index b02521c..0000000 --- a/src/main/java/com/nexters/moyeomoyeo/team_building/domain/entity/UserChoice.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.nexters.moyeomoyeo.team_building.domain.entity; - -import com.nexters.moyeomoyeo.common.entity.BaseEntity; -import jakarta.persistence.Column; -import jakarta.persistence.Entity; -import jakarta.persistence.FetchType; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import jakarta.persistence.JoinColumn; -import jakarta.persistence.ManyToOne; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.experimental.SuperBuilder; - -@Entity -@Getter -@NoArgsConstructor -@SuperBuilder -public class UserChoice extends BaseEntity { - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "id") - private Long id; - - @Column(name = "choice_order") - private Integer choiceOrder; - - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "user_id") - private User user; - - private String teamUuid; - - public void addUser(User user) { - this.user = user; - this.user.getChoices().add(this); - } -} diff --git a/src/main/java/com/nexters/moyeomoyeo/team_building/service/TeamBuildingAdminService.java b/src/main/java/com/nexters/moyeomoyeo/team_building/service/TeamBuildingAdminService.java index 58ab4b1..fe2c967 100644 --- a/src/main/java/com/nexters/moyeomoyeo/team_building/service/TeamBuildingAdminService.java +++ b/src/main/java/com/nexters/moyeomoyeo/team_building/service/TeamBuildingAdminService.java @@ -15,6 +15,8 @@ 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.repository.TeamBuildingRepository; +import jakarta.annotation.Nullable; import java.util.List; import java.util.Objects; import lombok.RequiredArgsConstructor; @@ -25,39 +27,44 @@ @RequiredArgsConstructor public class TeamBuildingAdminService { - private final TeamBuildingService teamBuildingService; private final UserService userService; private final NotificationService notificationService; + private final TeamBuildingRepository teamBuildingRepository; + + @Nullable + private static Team findTeam(String teamUuid, TeamBuilding teamBuilding) { + return teamBuilding.getTeams() + .stream() + .filter(team -> Objects.equals(team.getUuid(), teamUuid)) + .findFirst() + .orElse(null); + } @Transactional public UserInfo adjustUser(String teamBuildingUuid, String userUuid, String teamUuid) { - final TeamBuilding teamBuilding = teamBuildingService.findByUuid(teamBuildingUuid); + final TeamBuilding teamBuilding = 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); + final Team team = findTeam(teamUuid, teamBuilding); - user.adjustTeam(targetTeam); - user.updateSelectedRound(Objects.isNull(targetTeam) ? null : RoundStatus.ADJUSTED_ROUND); + user.adjustTeam(team); + user.updateSelectedRound(Objects.isNull(team) ? null : RoundStatus.ADJUSTED_ROUND); UserInfo userInfo = makeUserInfo(user); - notificationService.broadCast(teamBuildingUuid, "adjust-user", userInfo); + notificationService.broadcast(teamBuildingUuid, "adjust-user", userInfo); return userInfo; } @Transactional public void deleteTeamBuildingUser(String uuid, String userUuid) { - final TeamBuilding teamBuilding = teamBuildingService.findByUuid(uuid); + final TeamBuilding teamBuilding = findByUuid(uuid); - if (RoundStatus.FIRST_ROUND != teamBuilding.getRoundStatus()) { + if (RoundStatus.START != teamBuilding.getRoundStatus()) { throw ExceptionInfo.INVALID_DELETE_REQUEST.exception(); } userService.deleteUser(uuid, userUuid); @@ -65,38 +72,58 @@ public void deleteTeamBuildingUser(String uuid, String userUuid) { @Transactional public void finishTeamBuilding(String uuid) { - final TeamBuilding teamBuilding = teamBuildingService.findByUuid(uuid); - + final TeamBuilding teamBuilding = findByUuid(uuid); if (RoundStatus.ADJUSTED_ROUND != teamBuilding.getRoundStatus()) { throw ExceptionInfo.INVALID_FINISH_REQUEST.exception(); } + moveAllRoundStatus(teamBuilding); + notificationService.broadcast(teamBuilding.getUuid(), "finish-team-building", teamBuilding.getRoundStatus()); + } + + @Transactional + public void startTeamBuilding(String teamBuildingUuid) { + final TeamBuilding teamBuilding = findByUuid(teamBuildingUuid); + if (RoundStatus.START != teamBuilding.getRoundStatus()) { + throw ExceptionInfo.INVALID_FINISH_REQUEST.exception(); + } + + moveAllRoundStatus(teamBuilding); + notificationService.broadcast(teamBuilding.getUuid(), "start-team-building", teamBuilding.getRoundStatus()); + } + + private void moveAllRoundStatus(TeamBuilding teamBuilding) { teamBuilding.nextRound(); - notificationService.broadCast(teamBuilding.getUuid(), "finish-team-building", teamBuilding.getRoundStatus()); + for (Team team : teamBuilding.getTeams()) { + team.nextRound(); + } } @Transactional public TeamBuildingResponse createTeamBuilding(TeamBuildingRequest teamBuildingRequest) { - final TeamBuilding teamBuilding = TeamBuilding.builder() - .name(teamBuildingRequest.getName()) - .build(); - final List teams = teamBuildingRequest.getTeams() .stream() .map(TeamRequest::toEntity) .toList(); + final TeamBuilding teamBuilding = teamBuildingRepository.save(TeamBuilding.builder() + .name(teamBuildingRequest.getName()) + .teams(teams) + .build()); + 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()) + .teamBuildingInfo(makeTeamBuildingInfo(teamBuilding)) + .teamInfoList(teamBuilding.getTeams().stream().map(TeamInfo::makeTeamInfo).toList()) .build(); } + private TeamBuilding findByUuid(String teamBuildingUuid) { + return teamBuildingRepository.findByUuid(teamBuildingUuid) + .orElseThrow(ExceptionInfo.INVALID_TEAM_BUILDING_UUID::exception); + } } diff --git a/src/main/java/com/nexters/moyeomoyeo/team_building/service/TeamBuildingCoreService.java b/src/main/java/com/nexters/moyeomoyeo/team_building/service/TeamBuildingCoreService.java index 6ae9136..92e7585 100644 --- a/src/main/java/com/nexters/moyeomoyeo/team_building/service/TeamBuildingCoreService.java +++ b/src/main/java/com/nexters/moyeomoyeo/team_building/service/TeamBuildingCoreService.java @@ -1,34 +1,31 @@ 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.controller.dto.response.*; 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 com.nexters.moyeomoyeo.team_building.domain.repository.TeamBuildingRepository; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.List; +import java.util.Objects; + +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; + @Service @RequiredArgsConstructor public class TeamBuildingCoreService { - private final TeamBuildingService teamBuildingService; private final UserService userService; private final NotificationService notificationService; + private final TeamBuildingRepository teamBuildingRepository; /** * 선택된 유저가 현재 라운드에서 지망한 팀이 유저를 선택한 팀과 일치하는지 유효성 체크. @@ -40,8 +37,8 @@ public class TeamBuildingCoreService { private static boolean isChosenTeam(Team team, List 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())) { + final String teamUuid = user.findChoice(roundStatus.getOrder()); + if (!Objects.equals(teamUuid, team.getUuid())) { return false; } } @@ -66,66 +63,109 @@ private static boolean isAllTeamSelected(List teams, RoundStatus roundStat return true; } + private static Team findTeam(TeamBuilding teamBuilding, String teamUuid) { + return teamBuilding.getTeams() + .stream() + .filter(team -> teamUuid.equals(team.getUuid())) + .findFirst() + .orElseThrow(ExceptionInfo.INVALID_TEAM_UUID::exception); + } + + private static List makeUserInfo(List targetTeam) { + return targetTeam.stream().map(UserInfo::makeUserInfo).toList(); + } + + private static void addUserAndMoveTeamRound(Team targetTeam, List pickedUsers) { + for (final User user : pickedUsers) { + user.addTeam(targetTeam); + user.updateSelectedRound(targetTeam.getRoundStatus()); + } + targetTeam.nextRound(); + } + + private static void validateRequest(RoundStatus teamBuildingRoundStatus, Team targetTeam, List pickedUsers) { + if (!RoundStatus.isPickUserPossible(teamBuildingRoundStatus)) { + throw ExceptionInfo.BAD_REQUEST_FOR_USER_PICK.exception(); + } + + if (isSelectDone(teamBuildingRoundStatus, targetTeam.getRoundStatus())) { + throw ExceptionInfo.DUPLICATED_PICK_REQUEST.exception(); + } + + if (!isChosenTeam(targetTeam, pickedUsers)) { + throw ExceptionInfo.BAD_REQUEST_FOR_USER_PICK.exception(); + } + } + @Transactional(readOnly = true) public TeamBuildingResponse findTeamBuilding(String teamBuildingUuid) { - final TeamBuilding teamBuilding = teamBuildingService.findByUuid(teamBuildingUuid); - + final TeamBuilding teamBuilding = findByUuid(teamBuildingUuid); final List 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()) + .userInfoList(makeUserInfo(users)) + .build(); + } + + /** + * 설문 팀 조회시 user choice 는 다른 유저에게 숨겨져야함 + * + * @param teamBuildingUuid teambuilding uuid + * @return userInfo 가 제외된 팀빌딩 정보 + */ + @Transactional(readOnly = true) + public TeamBuildingResponse findTeamBuildingExcludingUser(String teamBuildingUuid) { + final TeamBuilding teamBuilding = findByUuid(teamBuildingUuid); + + return TeamBuildingResponse.builder() + .teamBuildingInfo(makeTeamBuildingInfo(teamBuilding)) + .teamInfoList(teamBuilding.getTeams().stream().map(TeamInfo::makeTeamInfo).toList()) .build(); } @Transactional public UserPickResponse pickUsers(String teamBuildingUuid, String teamUuid, UserPickRequest userPickRequest) { - final TeamBuilding teamBuilding = teamBuildingService.findByUuid(teamBuildingUuid); + final TeamBuilding teamBuilding = 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 Team team = findTeam(teamBuilding, teamUuid); final List userUuids = userPickRequest.getUserUuids(); final List pickedUsers = userService.findByUuidIn(userUuids); - if (!isChosenTeam(targetTeam, pickedUsers)) { - throw ExceptionInfo.BAD_REQUEST_FOR_USER_PICK.exception(); - } + validateRequest(teamBuildingRoundStatus, team, pickedUsers); - for (final User user : pickedUsers) { - user.addTeam(targetTeam); - user.updateSelectedRound(teamBuildingRoundStatus); - } - targetTeam.nextRound(); + addUserAndMoveTeamRound(team, pickedUsers); + moveTeamBuildingRoundIfAllSelected(teamBuilding); - PickUserResponse userResponse = PickUserResponse.builder() - .teamName(targetTeam.getName()) + broadcastPickedUsers(teamBuilding.getUuid(), team.getUuid(), team.getName(), userUuids); + + return UserPickResponse.builder() + .userInfoList(makeUserInfo(team.getUsers())) + .build(); + } + + private void broadcastPickedUsers(String teamBuildingUuid, String teamUuid, String teamName, List userUuids) { + final PickUserResponse userResponse = PickUserResponse.builder() .teamUuid(teamUuid) + .teamName(teamName) .pickUserUuids(userUuids) .build(); - notificationService.broadCast(teamBuilding.getUuid(), "pick-user", userResponse); + notificationService.broadcast(teamBuildingUuid, "pick-user", userResponse); + } - if (isAllTeamSelected(teamBuilding.getTeams(), teamBuildingRoundStatus)) { + private TeamBuilding findByUuid(String teamBuildingUuid) { + return teamBuildingRepository.findByUuid(teamBuildingUuid) + .orElseThrow(ExceptionInfo.INVALID_TEAM_BUILDING_UUID::exception); + } + + private void moveTeamBuildingRoundIfAllSelected(TeamBuilding teamBuilding) { + if (isAllTeamSelected(teamBuilding.getTeams(), teamBuilding.getRoundStatus())) { final RoundStatus nextStatus = teamBuilding.nextRound(); - notificationService.broadCast(teamBuilding.getUuid(), "change-round", nextStatus); + notificationService.broadcast(teamBuilding.getUuid(), "change-round", nextStatus); } - - return UserPickResponse.builder() - .userInfoList(targetTeam.getUsers().stream().map(UserInfo::makeUserInfo).toList()) - .build(); } } diff --git a/src/main/java/com/nexters/moyeomoyeo/team_building/service/TeamBuildingService.java b/src/main/java/com/nexters/moyeomoyeo/team_building/service/TeamBuildingService.java deleted file mode 100644 index 27476e8..0000000 --- a/src/main/java/com/nexters/moyeomoyeo/team_building/service/TeamBuildingService.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.nexters.moyeomoyeo.team_building.service; - - -import static com.nexters.moyeomoyeo.team_building.controller.dto.response.TeamBuildingResponse.TeamBuildingInfo.makeTeamBuildingInfo; - -import com.nexters.moyeomoyeo.common.constant.ExceptionInfo; -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.domain.entity.TeamBuilding; -import com.nexters.moyeomoyeo.team_building.domain.repository.TeamBuildingRepository; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -@Service -@RequiredArgsConstructor -public class TeamBuildingService { - - private final TeamBuildingRepository teamBuildingRepository; - - @Transactional(readOnly = true) - public TeamBuildingResponse findTeamBuildingAndTeams(String roomUuid) { - final TeamBuilding teamBuilding = findByUuid(roomUuid); - - return TeamBuildingResponse.builder() - .teamBuildingInfo(makeTeamBuildingInfo(teamBuilding)) - .teamInfoList(teamBuilding.getTeams().stream().map(TeamInfo::makeTeamInfo).toList()) - .build(); - } - - public TeamBuilding findByUuid(String teamBuildingUuid) { - return teamBuildingRepository.findByUuid(teamBuildingUuid) - .orElseThrow(ExceptionInfo.INVALID_TEAM_BUILDING_UUID::exception); - } - - public TeamBuilding save(TeamBuilding teamBuilding) { - return teamBuildingRepository.save(teamBuilding); - } -} diff --git a/src/main/java/com/nexters/moyeomoyeo/team_building/service/UserService.java b/src/main/java/com/nexters/moyeomoyeo/team_building/service/UserService.java index 8f3c9af..bfe7f7c 100644 --- a/src/main/java/com/nexters/moyeomoyeo/team_building/service/UserService.java +++ b/src/main/java/com/nexters/moyeomoyeo/team_building/service/UserService.java @@ -7,10 +7,8 @@ import com.nexters.moyeomoyeo.team_building.controller.dto.request.UserRequest; import com.nexters.moyeomoyeo.team_building.controller.dto.response.UserInfo; import com.nexters.moyeomoyeo.team_building.domain.entity.User; -import com.nexters.moyeomoyeo.team_building.domain.entity.UserChoice; import com.nexters.moyeomoyeo.team_building.domain.repository.UserRepository; import jakarta.transaction.Transactional; -import java.util.ArrayList; import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -22,11 +20,12 @@ public class UserService { private final NotificationService notificationService; private final UserRepository userRepository; - public static User makeUser(String teamBuildingUuid, UserRequest request) { + private static User makeUser(String teamBuildingUuid, UserRequest request) { return User.builder() .name(request.getName()) .position(request.getPosition()) .profileLink(request.getProfileLink()) + .choices(request.getChoices()) .teamBuildingUuid(teamBuildingUuid) .build(); } @@ -39,39 +38,17 @@ private static boolean isValidUser(List userUuids, List pickedUser public UserInfo createUser(String teamBuildingUuid, UserRequest request) { final User user = makeUser(teamBuildingUuid, request); - final List choices = createUserChoices(request.getChoices()); - for (final UserChoice choice : choices) { - choice.addUser(user); - } - UserInfo userInfo = makeUserInfo(userRepository.save(user)); - notificationService.broadCast(teamBuildingUuid, "create-user", userInfo); + notificationService.broadcast(teamBuildingUuid, "create-user", userInfo); return userInfo; } - public List createUserChoices(List teamUuids) { - final List choices = new ArrayList<>(); - int choiceOrder = 1; - - for (final String teamUuid : teamUuids) { - final UserChoice userChoice = UserChoice.builder() - .choiceOrder(choiceOrder++) - .teamUuid(teamUuid) - .build(); - - choices.add(userChoice); - } - return choices; - } - - @Transactional public void deleteUser(String teamBuildingUuid, String userUuid) { final User targetUser = findByUuid(userUuid); userRepository.delete(targetUser); - notificationService.broadCast(teamBuildingUuid, "delete-user", userUuid); - + notificationService.broadcast(teamBuildingUuid, "delete-user", userUuid); } public User findByUuid(String userUuid) { diff --git a/src/test/java/com/nexters/moyeomoyeo/team_building/fixture/FixtureTeamBuilding.java b/src/test/java/com/nexters/moyeomoyeo/team_building/fixture/FixtureTeamBuilding.java new file mode 100644 index 0000000..5944ae1 --- /dev/null +++ b/src/test/java/com/nexters/moyeomoyeo/team_building/fixture/FixtureTeamBuilding.java @@ -0,0 +1,38 @@ +package com.nexters.moyeomoyeo.team_building.fixture; + +import com.nexters.moyeomoyeo.team_building.domain.constant.Position; +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 java.util.List; + +public class FixtureTeamBuilding { + + public static TeamBuilding teamBuilding(RoundStatus roundStatus) { + return TeamBuilding.builder() + .roundStatus(roundStatus) + .name("넥스터즈 팀빌딩") + .teams(List.of( + Team.builder() + .name("team1") + .pmPosition(Position.IOS) + .roundStatus(roundStatus) + .build(), + Team.builder() + .name("team2") + .pmPosition(Position.ANDROID) + .roundStatus(roundStatus) + .build(), + Team.builder() + .name("team3") + .pmPosition(Position.FRONT_END) + .roundStatus(roundStatus) + .build(), + Team.builder() + .name("team4") + .pmPosition(Position.BACK_END) + .roundStatus(roundStatus) + .build())) + .build(); + } +} diff --git a/src/test/java/com/nexters/moyeomoyeo/team_building/service/TeamBuildingAdminServiceTest.java b/src/test/java/com/nexters/moyeomoyeo/team_building/service/TeamBuildingAdminServiceTest.java new file mode 100644 index 0000000..4775bb6 --- /dev/null +++ b/src/test/java/com/nexters/moyeomoyeo/team_building/service/TeamBuildingAdminServiceTest.java @@ -0,0 +1,141 @@ +package com.nexters.moyeomoyeo.team_building.service; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.BDDMockito.given; + +import com.nexters.moyeomoyeo.MoyeoMoyeoTest; +import com.nexters.moyeomoyeo.common.constant.ExceptionInfo; +import com.nexters.moyeomoyeo.common.exception.vo.CustomException; +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.UserInfo; +import com.nexters.moyeomoyeo.team_building.domain.constant.Position; +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.repository.TeamBuildingRepository; +import com.nexters.moyeomoyeo.team_building.domain.repository.UserRepository; +import com.nexters.moyeomoyeo.team_building.fixture.FixtureTeamBuilding; +import java.util.List; +import java.util.Optional; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.transaction.annotation.Transactional; + +@MoyeoMoyeoTest +class TeamBuildingAdminServiceTest { + + @Autowired + private TeamBuildingAdminService sut; + + @Autowired + private TeamBuildingRepository teamBuildingRepository; + + @Autowired + private UserRepository userRepository; + + @Test + void createTeamBuilding() { + final TeamBuildingResponse teamBuildingResponse = sut.createTeamBuilding(TeamBuildingRequest.builder() + .name("넥스터즈 팀빌딩이에요") + .teams(List.of( + TeamRequest.builder() + .name("team1") + .pmName("pm1") + .pmPosition(Position.FRONT_END) + .build(), + TeamRequest.builder() + .name("team2") + .pmName("pm2") + .pmPosition(Position.BACK_END) + .build())) + .build());; + + assertThat(teamBuildingResponse.getTeamBuildingInfo().getTeamBuildingName()).isEqualTo("넥스터즈 팀빌딩이에요"); + assertThat(teamBuildingResponse.getTeamInfoList().get(0).getTeamName()).isEqualTo("team1"); + assertThat(teamBuildingResponse.getTeamInfoList().get(0).getPmPosition()).isEqualTo(Position.FRONT_END); + } + + + @Transactional + @Test + @DisplayName("조정 단계에서 팀1 -> 팀2로 옮겨졌을 때") + void adjustUserToDifferentTeam() { + final TeamBuilding teamBuilding = teamBuildingRepository.save(FixtureTeamBuilding.teamBuilding(RoundStatus.ADJUSTED_ROUND)); + final Team team1 = teamBuilding.getTeams().get(0); + final Team team2 = teamBuilding.getTeams().get(1); + + final User user = userRepository.save(User.builder() + .name("넥터사람") + .position(Position.BACK_END) + .choices(List.of("1", "2", "3", "4")) + .team(team1) + .build()); + + final UserInfo adjustedUser = sut.adjustUser(teamBuilding.getUuid(), user.getUuid(), team2.getUuid()); + assertThat(adjustedUser.getJoinedTeamUuid()).isEqualTo(team2.getUuid()); + assertThat(adjustedUser.getSelectedRound()).isEqualTo(RoundStatus.ADJUSTED_ROUND); + } + + @Transactional + @Test + @DisplayName("조정 단계에서 할당됭 팀을 해제했을 때") + void adjustUserToNotAssigned() { + final TeamBuilding teamBuilding = teamBuildingRepository.save(FixtureTeamBuilding.teamBuilding(RoundStatus.ADJUSTED_ROUND)); + final Team team1 = teamBuilding.getTeams().get(0); + + final User user = userRepository.save(User.builder() + .name("넥터사람") + .position(Position.BACK_END) + .choices(List.of("1", "2", "3", "4")) + .team(team1) + .build()); + + final UserInfo adjustedUser = sut.adjustUser(teamBuilding.getUuid(), user.getUuid(), null); + assertThat(adjustedUser.getJoinedTeamUuid()).isNull(); + assertThat(adjustedUser.getSelectedRound()).isNull(); + } + + @Test + void deleteTeamBuildingUser() { + final TeamBuilding teamBuilding = teamBuildingRepository.save(FixtureTeamBuilding.teamBuilding(RoundStatus.START)); + + final User user = userRepository.save(User.builder() + .name("넥터사람") + .position(Position.BACK_END) + .choices(List.of("1", "2", "3", "4")) + .teamBuildingUuid(teamBuilding.getUuid()) + .build()); + + sut.deleteTeamBuildingUser(teamBuilding.getUuid(), user.getUuid()); + + assertThat(userRepository.findByUuid(user.getUuid())).isEmpty(); + } + + @Test + @Transactional + void finishTeamBuilding() { + final TeamBuilding teamBuilding = teamBuildingRepository.save(FixtureTeamBuilding.teamBuilding(RoundStatus.ADJUSTED_ROUND)); + + sut.finishTeamBuilding(teamBuilding.getUuid()); + + assertThat(teamBuilding.getRoundStatus()).isEqualTo(RoundStatus.COMPLETE); + assertThat(teamBuilding.getTeams().get(0).getRoundStatus()).isEqualTo(RoundStatus.COMPLETE); + } + + @Test + @Transactional + void startTeamBuilding() { + final TeamBuilding teamBuilding = teamBuildingRepository.save(FixtureTeamBuilding.teamBuilding(RoundStatus.START)); + + sut.startTeamBuilding(teamBuilding.getUuid()); + + assertThat(teamBuilding.getRoundStatus()).isEqualTo(RoundStatus.FIRST_ROUND); + assertThat(teamBuilding.getTeams().get(0).getRoundStatus()).isEqualTo(RoundStatus.FIRST_ROUND); + } +} diff --git a/src/test/java/com/nexters/moyeomoyeo/team_building/service/TeamBuildingCoreServiceTest.java b/src/test/java/com/nexters/moyeomoyeo/team_building/service/TeamBuildingCoreServiceTest.java new file mode 100644 index 0000000..33e8863 --- /dev/null +++ b/src/test/java/com/nexters/moyeomoyeo/team_building/service/TeamBuildingCoreServiceTest.java @@ -0,0 +1,116 @@ +package com.nexters.moyeomoyeo.team_building.service; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.nexters.moyeomoyeo.MoyeoMoyeoTest; +import com.nexters.moyeomoyeo.team_building.controller.dto.request.UserPickRequest; +import com.nexters.moyeomoyeo.team_building.controller.dto.response.UserPickResponse; +import com.nexters.moyeomoyeo.team_building.domain.constant.Position; +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.repository.TeamBuildingRepository; +import com.nexters.moyeomoyeo.team_building.domain.repository.UserRepository; +import com.nexters.moyeomoyeo.team_building.fixture.FixtureTeamBuilding; +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.transaction.annotation.Transactional; + +@MoyeoMoyeoTest +class TeamBuildingCoreServiceTest { + + @Autowired + private TeamBuildingCoreService sut; + + @Autowired + private TeamBuildingRepository teamBuildingRepository; + + @Autowired + private UserRepository userRepository; + + @Transactional + @Test + @DisplayName("첫번째 라운드에서 한 팀이 유저 선택 완료후 다음라운드로 넘어가는지") + void pickUserOne() { + final TeamBuilding teamBuilding = teamBuildingRepository.save(FixtureTeamBuilding.teamBuilding(RoundStatus.FIRST_ROUND)); + + final List teams = teamBuilding.getTeams(); + final Team sutTeam = teams.get(0); + final User user = userRepository.save(User.builder() + .name("넥터사람") + .position(Position.BACK_END) + .choices(List.of(sutTeam.getUuid(), teams.get(1).getUuid(), teams.get(2).getUuid(), teams.get(3).getUuid())) + .teamBuildingUuid(teamBuilding.getUuid()) + .build()); + + final UserPickResponse userPickResponse = sut.pickUsers(teamBuilding.getUuid(), sutTeam.getUuid(), UserPickRequest.builder() + .userUuids(List.of(user.getUuid())) + .build()); + + assertThat(userPickResponse.getUserInfoList().get(0).getUserName()).isEqualTo("넥터사람"); + assertThat(userPickResponse.getUserInfoList().get(0).getPosition()).isEqualTo(Position.BACK_END); + assertThat(userPickResponse.getUserInfoList().get(0).getSelectedRound()).isEqualTo(RoundStatus.FIRST_ROUND); + assertThat(sutTeam.getRoundStatus()).isEqualTo(RoundStatus.SECOND_ROUND); + } + + @Transactional + @Test + @DisplayName("첫번째 라운드에서 한 팀이 유저 선택을 아무도 하지 않은 후 다음라운드로 넘어가는지") + void pickUserNoOne() { + final TeamBuilding teamBuilding = teamBuildingRepository.save(FixtureTeamBuilding.teamBuilding(RoundStatus.FIRST_ROUND)); + + final List teams = teamBuilding.getTeams(); + final Team sutTeam = teams.get(0); + + final UserPickResponse userPickResponse = sut.pickUsers(teamBuilding.getUuid(), sutTeam.getUuid(), UserPickRequest.builder() + .userUuids(List.of()) + .build()); + + assertThat(userPickResponse.getUserInfoList()).isEmpty(); + assertThat(sutTeam.getRoundStatus()).isEqualTo(RoundStatus.SECOND_ROUND); + } + + @Transactional + @Test + @DisplayName("첫번째 라운드에서 모든 팀이 유저 선택 완료 후 팀빌딩이 다음라운드로 넘어가는지") + void pickUserALL() { + final TeamBuilding teamBuilding = teamBuildingRepository.save(FixtureTeamBuilding.teamBuilding(RoundStatus.FIRST_ROUND)); + + final List teams = teamBuilding.getTeams(); + + final User user1 = userRepository.save(User.builder() + .name("넥터사람1") + .position(Position.BACK_END) + .choices(List.of(teams.get(0).getUuid(), teams.get(1).getUuid(), teams.get(2).getUuid(), teams.get(3).getUuid())) + .teamBuildingUuid(teamBuilding.getUuid()) + .build()); + + final User user2 = userRepository.save(User.builder() + .name("넥터사람2") + .position(Position.FRONT_END) + .choices(List.of(teams.get(0).getUuid(), teams.get(1).getUuid(), teams.get(2).getUuid(), teams.get(3).getUuid())) + .teamBuildingUuid(teamBuilding.getUuid()) + .build()); + + sut.pickUsers(teamBuilding.getUuid(), teams.get(0).getUuid(), UserPickRequest.builder() + .userUuids(List.of(user1.getUuid(), user2.getUuid())) + .build()); + + sut.pickUsers(teamBuilding.getUuid(), teams.get(1).getUuid(), UserPickRequest.builder() + .userUuids(List.of()) + .build()); + + sut.pickUsers(teamBuilding.getUuid(), teams.get(2).getUuid(), UserPickRequest.builder() + .userUuids(List.of()) + .build()); + + sut.pickUsers(teamBuilding.getUuid(), teams.get(3).getUuid(), UserPickRequest.builder() + .userUuids(List.of()) + .build()); + + assertThat(teamBuilding.getRoundStatus()).isEqualTo(RoundStatus.SECOND_ROUND); + } +} diff --git a/src/test/java/com/nexters/moyeomoyeo/team_building/service/TeamBuildingServiceTest.java b/src/test/java/com/nexters/moyeomoyeo/team_building/service/TeamBuildingServiceTest.java deleted file mode 100644 index bbd7e03..0000000 --- a/src/test/java/com/nexters/moyeomoyeo/team_building/service/TeamBuildingServiceTest.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.nexters.moyeomoyeo.team_building.service; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -import com.nexters.moyeomoyeo.MoyeoMoyeoTest; -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.domain.constant.Position; -import com.nexters.moyeomoyeo.team_building.domain.constant.RoundStatus; -import java.util.List; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; - -@MoyeoMoyeoTest -class TeamBuildingServiceTest { - - @Autowired - private TeamBuildingService teamBuildingService; - - @Autowired - private TeamBuildingAdminService adminService; - - - @Test - void createTeamBuilding() { - final var saveResponse = saveTeamBuildingWithTeams(); - final TeamBuildingResponse findResponse = teamBuildingService.findTeamBuildingAndTeams( - saveResponse.getTeamBuildingInfo().getTeamBuildingUrl()); - - // team building - assertEquals(saveResponse.getTeamBuildingInfo().getTeamBuildingUrl(), - findResponse.getTeamBuildingInfo().getTeamBuildingUrl()); - assertEquals(RoundStatus.FIRST_ROUND, findResponse.getTeamBuildingInfo().getRoundStatus()); - - //team - assertEquals(saveResponse.getTeamInfoList().get(0).getTeamName(), - findResponse.getTeamInfoList().get(0).getTeamName()); - assertEquals(saveResponse.getTeamInfoList().get(1).getTeamName(), - findResponse.getTeamInfoList().get(1).getTeamName()); - } - - private TeamBuildingResponse saveTeamBuildingWithTeams() { - return adminService.createTeamBuilding(TeamBuildingRequest.builder() - .name("team-Building") - .teams(List.of( - TeamRequest.builder() - .name("team1") - .pmName("pm1") - .pmPosition(Position.FRONT_END) - .build(), - TeamRequest.builder() - .name("team2") - .pmName("pm2") - .pmPosition(Position.BACK_END) - .build())) - .build()); - } -} diff --git a/src/test/java/com/nexters/moyeomoyeo/team_building/service/UserServiceTest.java b/src/test/java/com/nexters/moyeomoyeo/team_building/service/UserServiceTest.java new file mode 100644 index 0000000..8fe9f06 --- /dev/null +++ b/src/test/java/com/nexters/moyeomoyeo/team_building/service/UserServiceTest.java @@ -0,0 +1,49 @@ +package com.nexters.moyeomoyeo.team_building.service; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.*; + +import com.nexters.moyeomoyeo.MoyeoMoyeoTest; +import com.nexters.moyeomoyeo.common.constant.ExceptionInfo; +import com.nexters.moyeomoyeo.common.exception.vo.CustomException; +import com.nexters.moyeomoyeo.team_building.controller.dto.request.UserRequest; +import com.nexters.moyeomoyeo.team_building.controller.dto.response.UserInfo; +import com.nexters.moyeomoyeo.team_building.domain.constant.Position; +import java.util.List; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; + +@MoyeoMoyeoTest +class UserServiceTest { + + @Autowired + private UserService sut; + + @Test + void createUser() { + final UserInfo userInfo = sut.createUser("team-building-uuid", UserRequest.builder() + .name("넥터사람") + .position(Position.BACK_END) + .choices(List.of("1", "2", "3", "4")) + .build()); + + assertThat(userInfo.getUserName()).isEqualTo("넥터사람"); + assertThat(userInfo.getPosition()).isEqualTo(Position.BACK_END); + assertThat(userInfo.getChoices().get(0)).isEqualTo("1"); + } + + @Test + void deleteUser() { + final UserInfo createdUser = sut.createUser("team-building-uuid", UserRequest.builder() + .name("넥터사람") + .position(Position.BACK_END) + .choices(List.of("1", "2", "3", "4")) + .build()); + + sut.deleteUser("team-building-uuid", createdUser.getUuid()); + + assertThatThrownBy(() -> sut.findByUuid(createdUser.getUuid())) + .isInstanceOf(CustomException.class).hasMessage(ExceptionInfo.INVALID_USER_UUID.getMessage()); + } +}