diff --git a/src/main/java/org/pingle/pingleserver/controller/TeamController.java b/src/main/java/org/pingle/pingleserver/controller/TeamController.java index b1d5390..4271105 100644 --- a/src/main/java/org/pingle/pingleserver/controller/TeamController.java +++ b/src/main/java/org/pingle/pingleserver/controller/TeamController.java @@ -6,6 +6,9 @@ import org.pingle.pingleserver.annotation.UserId; import org.pingle.pingleserver.controller.swagger.TeamApi; import org.pingle.pingleserver.dto.common.ApiResponse; +import org.pingle.pingleserver.dto.reponse.TeamCreationResponse; +import org.pingle.pingleserver.dto.reponse.TeamNameDuplicatedResponse; +import org.pingle.pingleserver.dto.request.TeamCreationRequest; import org.pingle.pingleserver.dto.request.TeamRegisterRequest; import org.pingle.pingleserver.dto.response.SelectedTeamResponse; import org.pingle.pingleserver.dto.response.TeamRegisterResponse; @@ -40,4 +43,14 @@ public ApiResponse registerTeam( @Valid @RequestBody TeamRegisterRequest request){ return ApiResponse.success(SuccessMessage.OK, teamService.registerTeam(userId, teamId, request)); } + + @GetMapping("/check-name") + public ApiResponse checkTeamName(@NotBlank @RequestParam String name){ + return ApiResponse.success(SuccessMessage.OK, teamService.checkTeamName(name)); + } + + @PostMapping + public ApiResponse createTeam(@UserId Long userId, @Valid @RequestBody TeamCreationRequest request){ + return ApiResponse.success(SuccessMessage.OK, teamService.createTeam(userId, request)); + } } diff --git a/src/main/java/org/pingle/pingleserver/domain/Team.java b/src/main/java/org/pingle/pingleserver/domain/Team.java index f4f7ce4..4562ed3 100644 --- a/src/main/java/org/pingle/pingleserver/domain/Team.java +++ b/src/main/java/org/pingle/pingleserver/domain/Team.java @@ -2,6 +2,7 @@ import jakarta.persistence.*; import lombok.AccessLevel; +import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; import org.pingle.pingleserver.domain.enums.TKeyword; @@ -21,6 +22,16 @@ public class Team extends BaseTimeEntity { private String code; + private String email; + @Enumerated(EnumType.STRING) private TKeyword keyword; + + @Builder + public Team(String name, String email, String code, TKeyword keyword) { + this.name = name; + this.email = email; + this.code = code; + this.keyword = keyword; + } } diff --git a/src/main/java/org/pingle/pingleserver/dto/reponse/TeamCreationResponse.java b/src/main/java/org/pingle/pingleserver/dto/reponse/TeamCreationResponse.java new file mode 100644 index 0000000..679fd3b --- /dev/null +++ b/src/main/java/org/pingle/pingleserver/dto/reponse/TeamCreationResponse.java @@ -0,0 +1,16 @@ +package org.pingle.pingleserver.dto.reponse; + +import org.pingle.pingleserver.domain.Team; +import org.pingle.pingleserver.domain.enums.TKeyword; + +public record TeamCreationResponse ( + Long id, + String name, + String email, + String code, + TKeyword keyword +) { + public static TeamCreationResponse of(Team team) { + return new TeamCreationResponse(team.getId(), team.getName(), team.getEmail(), team.getCode(), team.getKeyword()); + } +} diff --git a/src/main/java/org/pingle/pingleserver/dto/reponse/TeamNameDuplicatedResponse.java b/src/main/java/org/pingle/pingleserver/dto/reponse/TeamNameDuplicatedResponse.java new file mode 100644 index 0000000..e6c6aeb --- /dev/null +++ b/src/main/java/org/pingle/pingleserver/dto/reponse/TeamNameDuplicatedResponse.java @@ -0,0 +1,4 @@ +package org.pingle.pingleserver.dto.reponse; + +public record TeamNameDuplicatedResponse (boolean result){ +} diff --git a/src/main/java/org/pingle/pingleserver/dto/request/TeamCreationRequest.java b/src/main/java/org/pingle/pingleserver/dto/request/TeamCreationRequest.java new file mode 100644 index 0000000..6a78764 --- /dev/null +++ b/src/main/java/org/pingle/pingleserver/dto/request/TeamCreationRequest.java @@ -0,0 +1,10 @@ +package org.pingle.pingleserver.dto.request; + +import org.pingle.pingleserver.domain.enums.TKeyword; + +public record TeamCreationRequest ( + String name, + String email, + TKeyword keyword +) { +} diff --git a/src/main/java/org/pingle/pingleserver/dto/type/ErrorMessage.java b/src/main/java/org/pingle/pingleserver/dto/type/ErrorMessage.java index 3bb7174..cb6b602 100644 --- a/src/main/java/org/pingle/pingleserver/dto/type/ErrorMessage.java +++ b/src/main/java/org/pingle/pingleserver/dto/type/ErrorMessage.java @@ -27,6 +27,7 @@ public enum ErrorMessage { MISSING_REQUIRED_HEADER(HttpStatus.BAD_REQUEST, "필수 헤더가 누락되었습니다."), MISSING_REQUIRED_PARAMETER(HttpStatus.BAD_REQUEST, "필수 파라미터가 누락되었습니다."), GROUP_OWNER_DELETION_DENIED(HttpStatus.BAD_REQUEST, "그룹 장은 탈퇴할 수 없습니다."), + DUPLICATED_TEAM_NAME(HttpStatus.BAD_REQUEST, "중복된 팀 이름입니다."), // Authorization Error 401 TOKEN_MALFORMED_ERROR(HttpStatus.UNAUTHORIZED, "유효하지 않은 토큰입니다."), UNAUTHORIZED_ERROR(HttpStatus.UNAUTHORIZED, "토큰이 제공되지 않았거나 유효하지 않습니다."), diff --git a/src/main/java/org/pingle/pingleserver/repository/TeamRepository.java b/src/main/java/org/pingle/pingleserver/repository/TeamRepository.java index 4a286bc..9e694f3 100644 --- a/src/main/java/org/pingle/pingleserver/repository/TeamRepository.java +++ b/src/main/java/org/pingle/pingleserver/repository/TeamRepository.java @@ -25,4 +25,6 @@ default Team findByIdOrThrow(Long teamId) { "WHERE t.id = :teamId " + "GROUP BY t") Optional findTeamDetailsWithCounts(Long teamId); + + boolean existsByNameIgnoreCase(String name); } diff --git a/src/main/java/org/pingle/pingleserver/service/TeamService.java b/src/main/java/org/pingle/pingleserver/service/TeamService.java index d7a66dd..7847d26 100644 --- a/src/main/java/org/pingle/pingleserver/service/TeamService.java +++ b/src/main/java/org/pingle/pingleserver/service/TeamService.java @@ -5,6 +5,9 @@ import org.pingle.pingleserver.domain.User; import org.pingle.pingleserver.domain.UserTeam; import org.pingle.pingleserver.domain.enums.TRole; +import org.pingle.pingleserver.dto.reponse.TeamCreationResponse; +import org.pingle.pingleserver.dto.reponse.TeamNameDuplicatedResponse; +import org.pingle.pingleserver.dto.request.TeamCreationRequest; import org.pingle.pingleserver.dto.request.TeamRegisterRequest; import org.pingle.pingleserver.dto.response.SelectedTeamResponse; import org.pingle.pingleserver.dto.response.TeamDetailDto; @@ -22,6 +25,7 @@ import java.util.Comparator; import java.util.List; import java.util.stream.Collectors; +import java.util.Random; @Service @RequiredArgsConstructor @@ -66,4 +70,46 @@ public TeamRegisterResponse registerTeam(Long userId, Long teamId, TeamRegisterR userTeamRepository.save(newUserTeam); return TeamRegisterResponse.of(team.getId(), team.getName()); } + + public TeamNameDuplicatedResponse checkTeamName(String name) { + return new TeamNameDuplicatedResponse(!teamRepository.existsByNameIgnoreCase(name)); + } + + @Transactional + public TeamCreationResponse createTeam(Long userId, TeamCreationRequest request) { + User user = userRepository.findByIdOrThrow(userId); + if (teamRepository.existsByNameIgnoreCase(request.name())) { + throw new CustomException(ErrorMessage.DUPLICATED_TEAM_NAME); + } + + String code = generateCode(); + Team team = Team.builder() + .name(request.name()) + .email(request.email()) + .keyword(request.keyword()) + .code(code) + .build(); + teamRepository.save(team); + + UserTeam userTeam = UserTeam.builder() + .user(user) + .team(team) + .teamRole(TRole.OWNER) + .build(); + userTeamRepository.save(userTeam); + + return TeamCreationResponse.of(team); + } + + private String generateCode() { + String characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + StringBuilder result = new StringBuilder(12); + Random random = new Random(); + + for (int i = 0; i < 12; i++) { + int index = random.nextInt(characters.length()); + result.append(characters.charAt(index)); + } + return result.toString(); + } }