-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #31 from wvssm/develop
[스프린트 3] 강수민 - 팀 생성 기능 추가
- Loading branch information
Showing
14 changed files
with
470 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
40 changes: 40 additions & 0 deletions
40
src/main/java/PNUMEAT/Backend/domain/team/controller/TeamController.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
package PNUMEAT.Backend.domain.team.controller; | ||
|
||
import PNUMEAT.Backend.domain.auth.dto.request.MemberProfileRequest; | ||
import PNUMEAT.Backend.domain.auth.entity.Member; | ||
import PNUMEAT.Backend.domain.auth.service.MemberService; | ||
import PNUMEAT.Backend.domain.team.dto.request.TeamRequest; | ||
import PNUMEAT.Backend.domain.team.service.TeamService; | ||
import PNUMEAT.Backend.global.error.dto.response.ApiResponse; | ||
import PNUMEAT.Backend.global.security.annotation.LoginMember; | ||
import jakarta.validation.Valid; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.http.HttpStatus; | ||
import org.springframework.http.MediaType; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.stereotype.Controller; | ||
import org.springframework.web.bind.annotation.*; | ||
import org.springframework.web.multipart.MultipartFile; | ||
|
||
import static PNUMEAT.Backend.global.response.ResponseMessageEnum.TEAM_CREATED_SUCCESS; | ||
|
||
@RestController | ||
@RequestMapping("/api/v1/teams") | ||
@RequiredArgsConstructor | ||
public class TeamController { | ||
|
||
private final TeamService teamService; | ||
|
||
@PostMapping | ||
public ResponseEntity<ApiResponse<?>> createTeam(@ModelAttribute @Valid TeamRequest teamRequest, | ||
@RequestPart(value = "teamIcon", required = false) MultipartFile teamIcon, | ||
@LoginMember Member member){ | ||
teamService.createTeam(teamRequest, teamIcon, member); | ||
|
||
return ResponseEntity.status(TEAM_CREATED_SUCCESS.getStatusCode()) | ||
.contentType(MediaType.APPLICATION_JSON) | ||
.body(ApiResponse.createResponseWithMessage(TEAM_CREATED_SUCCESS.getMessage())); | ||
} | ||
} | ||
|
||
|
43 changes: 43 additions & 0 deletions
43
src/main/java/PNUMEAT/Backend/domain/team/dto/request/TeamRequest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
package PNUMEAT.Backend.domain.team.dto.request; | ||
|
||
import PNUMEAT.Backend.global.validation.annotation.NotNullOrBlank; | ||
import jakarta.validation.constraints.*; | ||
|
||
public record TeamRequest( | ||
@NotNullOrBlank | ||
@Pattern( | ||
regexp = "^[가-힣a-zA-Z0-9\\s]*$", | ||
message = "한글, 영어, 숫자, 공백만 입력 가능합니다." | ||
) | ||
@Size( | ||
max = 10, | ||
message = "글자 수를 초과했습니다." | ||
) | ||
String teamName, | ||
|
||
@Pattern( | ||
regexp = "^[가-힣a-zA-Z0-9!@#$%^&*()_+\\-=\\[\\]{};':\"\\\\|,.<>/?`~ ]*$", | ||
message = "팀 설명은 한글, 영어, 숫자, 기본 특수문자만 사용가능합니다." | ||
) | ||
@Size( | ||
max = 50, | ||
message = "글자 수를 초과했습니다." | ||
) | ||
String teamExplain, | ||
|
||
@NotNullOrBlank | ||
String topic, | ||
|
||
@NotNullOrBlank | ||
@Digits(integer = Integer.MAX_VALUE, fraction = 0, message = "2 ~ 20 사이의 숫자를 입력해주세요.") | ||
@Min(value = 2, message = "2 ~ 20 사이의 숫자를 입력해주세요.") | ||
@Max(value = 20, message = "2 ~ 20 사이의 숫자를 입력해주세요.") | ||
int memberLimit, | ||
|
||
@Pattern( | ||
regexp = "^[0-9]{4}$", | ||
message = "숫자 4자리를 입력해주세요." | ||
) | ||
String password | ||
) { | ||
} |
66 changes: 66 additions & 0 deletions
66
src/main/java/PNUMEAT/Backend/domain/team/entity/Team.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
package PNUMEAT.Backend.domain.team.entity; | ||
|
||
import PNUMEAT.Backend.domain.auth.entity.Member; | ||
import PNUMEAT.Backend.domain.team.enums.Topic; | ||
import PNUMEAT.Backend.domain.team_member.entity.TeamMember; | ||
import jakarta.persistence.*; | ||
import lombok.Builder; | ||
import lombok.Getter; | ||
import org.springframework.data.annotation.CreatedDate; | ||
import org.springframework.data.jpa.domain.support.AuditingEntityListener; | ||
|
||
import java.time.LocalDateTime; | ||
import java.util.ArrayList; | ||
import java.util.List; | ||
|
||
import static PNUMEAT.Backend.global.images.ImageConstant.DEFAULT_TEAM_IMAGE_URL; | ||
|
||
@Entity | ||
@Getter | ||
@EntityListeners(AuditingEntityListener.class) | ||
public class Team { | ||
@Id | ||
@GeneratedValue(strategy = GenerationType.IDENTITY) | ||
private Long teamId; | ||
|
||
private String teamName; | ||
|
||
private String teamIconUrl = DEFAULT_TEAM_IMAGE_URL; | ||
|
||
private Topic teamTopic; | ||
|
||
private String teamExplain; | ||
|
||
private int maxParticipant; | ||
|
||
private String teamPassword; | ||
|
||
@CreatedDate | ||
private LocalDateTime createdAt; | ||
|
||
private int streakDays; | ||
|
||
@ManyToOne | ||
@JoinColumn(name = "member_id") | ||
private Member teamManager; | ||
|
||
@OneToMany(mappedBy = "team") | ||
private List<TeamMember> teamMembers = new ArrayList<>(); | ||
|
||
protected Team(){ | ||
} | ||
|
||
@Builder | ||
public Team(String teamName, Topic teamTopic, String teamExplain, int maxParticipant, String teamPassword, Member teamManager) { | ||
this.teamName = teamName; | ||
this.teamTopic = teamTopic; | ||
this.teamExplain = teamExplain; | ||
this.maxParticipant = maxParticipant; | ||
this.teamPassword = teamPassword; | ||
this.teamManager = teamManager; | ||
} | ||
|
||
public void updateTeamIconUrl(String teamIconUrl){ | ||
this.teamIconUrl = teamIconUrl; | ||
} | ||
} |
36 changes: 36 additions & 0 deletions
36
src/main/java/PNUMEAT/Backend/domain/team/enums/Topic.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
package PNUMEAT.Backend.domain.team.enums; | ||
|
||
import PNUMEAT.Backend.global.error.ErrorCode; | ||
import PNUMEAT.Backend.global.error.Team24Exception; | ||
|
||
import static PNUMEAT.Backend.global.error.ErrorCode.TOPIC_INVALID_ERROR; | ||
|
||
public enum Topic { | ||
CODINGTEST(1, "코딩테스트"), | ||
STUDY(2, "스터디"); | ||
|
||
private final int code; | ||
private final String name; | ||
|
||
Topic(int code, String name) { | ||
this.code = code; | ||
this.name = name; | ||
} | ||
|
||
public int getCode() { | ||
return code; | ||
} | ||
|
||
public String getName() { | ||
return name; | ||
} | ||
|
||
public static Topic fromName(String name){ | ||
for(Topic topic : Topic.values()){ | ||
if(topic.getName().equals(name)){ | ||
return topic; | ||
} | ||
} | ||
throw new Team24Exception(TOPIC_INVALID_ERROR); | ||
} | ||
} |
7 changes: 7 additions & 0 deletions
7
src/main/java/PNUMEAT/Backend/domain/team/repository/TeamRepository.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package PNUMEAT.Backend.domain.team.repository; | ||
|
||
import PNUMEAT.Backend.domain.team.entity.Team; | ||
import org.springframework.data.jpa.repository.JpaRepository; | ||
|
||
public interface TeamRepository extends JpaRepository<Team, Long> { | ||
} |
49 changes: 49 additions & 0 deletions
49
src/main/java/PNUMEAT/Backend/domain/team/service/TeamService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
package PNUMEAT.Backend.domain.team.service; | ||
|
||
import PNUMEAT.Backend.domain.auth.entity.Member; | ||
import PNUMEAT.Backend.domain.team.dto.request.TeamRequest; | ||
import PNUMEAT.Backend.domain.team.entity.Team; | ||
import PNUMEAT.Backend.domain.team.enums.Topic; | ||
import PNUMEAT.Backend.domain.team.repository.TeamRepository; | ||
import PNUMEAT.Backend.domain.team_member.entity.TeamMember; | ||
import PNUMEAT.Backend.domain.team_member.repository.TeamMemberRepository; | ||
import PNUMEAT.Backend.global.images.ImageService; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.stereotype.Service; | ||
import org.springframework.transaction.annotation.Transactional; | ||
import org.springframework.web.multipart.MultipartFile; | ||
|
||
@Service | ||
@Transactional(readOnly = true) | ||
@RequiredArgsConstructor | ||
public class TeamService { | ||
|
||
private final TeamRepository teamRepository; | ||
private final TeamMemberRepository teamMemberRepository; | ||
private final ImageService imageService; | ||
|
||
@Transactional | ||
public Team createTeam(TeamRequest teamRequest, | ||
MultipartFile teamIcon, Member member){ | ||
|
||
Team team = Team.builder() | ||
.teamName(teamRequest.teamName()) | ||
.teamExplain(teamRequest.teamExplain()) | ||
.teamTopic(Topic.fromName(teamRequest.topic())) | ||
.maxParticipant(teamRequest.memberLimit()) | ||
.teamPassword(teamRequest.password()) | ||
.teamManager(member) | ||
.build(); | ||
|
||
if (teamIcon != null){ | ||
String teamIconUrl = imageService.teamImageUpload(teamIcon); | ||
team.updateTeamIconUrl(teamIconUrl); | ||
} | ||
|
||
TeamMember teamMember = new TeamMember(team, member); | ||
|
||
teamMemberRepository.save(teamMember); | ||
|
||
return teamRepository.save(team); | ||
} | ||
} |
42 changes: 42 additions & 0 deletions
42
src/main/java/PNUMEAT/Backend/domain/team_member/entity/TeamMember.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
package PNUMEAT.Backend.domain.team_member.entity; | ||
|
||
import PNUMEAT.Backend.domain.auth.entity.Member; | ||
import PNUMEAT.Backend.domain.team.entity.Team; | ||
import jakarta.persistence.*; | ||
|
||
import java.util.Objects; | ||
|
||
@Entity | ||
public class TeamMember { | ||
@Id | ||
@GeneratedValue(strategy = GenerationType.IDENTITY) | ||
private Long teamInfoId; | ||
|
||
@ManyToOne | ||
@JoinColumn(name="member_id") | ||
private Member member; | ||
|
||
@ManyToOne | ||
@JoinColumn(name="team_id") | ||
private Team team; | ||
|
||
protected TeamMember(){} | ||
|
||
public TeamMember(Team team, Member member) { | ||
this.member = member; | ||
this.team = team; | ||
} | ||
|
||
@Override | ||
public boolean equals(Object o) { | ||
if (this == o) return true; | ||
if (o == null || getClass() != o.getClass()) return false; | ||
TeamMember that = (TeamMember) o; | ||
return Objects.equals(teamInfoId, that.teamInfoId) && Objects.equals(member, that.member) && Objects.equals(team, that.team); | ||
} | ||
|
||
@Override | ||
public int hashCode() { | ||
return Objects.hash(teamInfoId, member, team); | ||
} | ||
} |
9 changes: 9 additions & 0 deletions
9
src/main/java/PNUMEAT/Backend/domain/team_member/repository/TeamMemberRepository.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package PNUMEAT.Backend.domain.team_member.repository; | ||
|
||
import PNUMEAT.Backend.domain.team_member.entity.TeamMember; | ||
import org.springframework.data.jpa.repository.JpaRepository; | ||
import org.springframework.stereotype.Repository; | ||
|
||
@Repository | ||
public interface TeamMemberRepository extends JpaRepository<TeamMember, Long> { | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
18 changes: 18 additions & 0 deletions
18
src/main/java/PNUMEAT/Backend/global/response/ResponseMessageEnum.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package PNUMEAT.Backend.global.response; | ||
|
||
import lombok.Getter; | ||
|
||
@Getter | ||
public enum ResponseMessageEnum { | ||
// TEAM | ||
TEAM_CREATED_SUCCESS("팀이 성공적으로 생성되었습니다.", 201); | ||
|
||
|
||
private final String message; | ||
private final int statusCode; | ||
|
||
ResponseMessageEnum(String message, int statusCode) { | ||
this.message = message; | ||
this.statusCode = statusCode; | ||
} | ||
} |
19 changes: 19 additions & 0 deletions
19
src/main/java/PNUMEAT/Backend/global/validation/annotation/NotNullOrBlank.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package PNUMEAT.Backend.global.validation.annotation; | ||
|
||
import PNUMEAT.Backend.global.validation.validator.NotNullOrBlankValidator; | ||
import jakarta.validation.Constraint; | ||
import jakarta.validation.Payload; | ||
|
||
import java.lang.annotation.ElementType; | ||
import java.lang.annotation.Retention; | ||
import java.lang.annotation.RetentionPolicy; | ||
import java.lang.annotation.Target; | ||
|
||
@Target(ElementType.FIELD) | ||
@Retention(RetentionPolicy.RUNTIME) | ||
@Constraint(validatedBy = NotNullOrBlankValidator.class) | ||
public @interface NotNullOrBlank { | ||
String message() default "값은 null이거나 공백만 입력될 수 없습니다."; | ||
Class<?>[] groups() default {}; | ||
Class<? extends Payload>[] payload() default {}; | ||
} |
12 changes: 12 additions & 0 deletions
12
src/main/java/PNUMEAT/Backend/global/validation/validator/NotNullOrBlankValidator.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package PNUMEAT.Backend.global.validation.validator; | ||
|
||
import PNUMEAT.Backend.global.validation.annotation.NotNullOrBlank; | ||
import jakarta.validation.ConstraintValidator; | ||
import jakarta.validation.ConstraintValidatorContext; | ||
|
||
public class NotNullOrBlankValidator implements ConstraintValidator<NotNullOrBlank, String> { | ||
@Override | ||
public boolean isValid(String value, ConstraintValidatorContext context) { | ||
return value != null && !value.trim().isEmpty(); | ||
} | ||
} |
Oops, something went wrong.