diff --git a/src/main/java/com/dnd/reevserver/domain/member/entity/Member.java b/src/main/java/com/dnd/reevserver/domain/member/entity/Member.java index 57a5556..d5c36d5 100644 --- a/src/main/java/com/dnd/reevserver/domain/member/entity/Member.java +++ b/src/main/java/com/dnd/reevserver/domain/member/entity/Member.java @@ -1,19 +1,20 @@ package com.dnd.reevserver.domain.member.entity; -import jakarta.persistence.Column; -import jakarta.persistence.Entity; -import jakarta.persistence.Id; -import jakarta.persistence.Table; +import com.dnd.reevserver.domain.userTeam.entity.UserTeam; +import jakarta.persistence.*; import lombok.*; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.oauth2.core.user.OAuth2User; +import java.util.ArrayList; import java.util.Collection; +import java.util.List; import java.util.Map; @Entity @Table(name = "Member") @Getter +@Setter @Builder @AllArgsConstructor @NoArgsConstructor(access = AccessLevel.PROTECTED) @@ -34,6 +35,9 @@ public class Member implements OAuth2User { @Column(name = "role", nullable = false, length = 100) private String role; + @OneToMany(mappedBy = "member") + private List userGroups = new ArrayList<>(); + @Column(name = "job", nullable = false, length = 100) private String job; @@ -60,7 +64,21 @@ public void updateProfileUrl(String newProfileUrl) { this.profileUrl = newProfileUrl; } + + + public Member(String userId, String nickname, String profileUrl, String role) { + this.userId = userId; + this.nickname = nickname; + this.profileUrl = profileUrl; + this.role = role; + } + + public void addUserGroup(UserTeam userGroup) { + userGroups.add(userGroup); + userGroup.setMember(this); + public void updateJob(String updateJob) { this.job = updateJob; + } } diff --git a/src/main/java/com/dnd/reevserver/domain/team/controller/TeamController.java b/src/main/java/com/dnd/reevserver/domain/team/controller/TeamController.java new file mode 100644 index 0000000..e759bfa --- /dev/null +++ b/src/main/java/com/dnd/reevserver/domain/team/controller/TeamController.java @@ -0,0 +1,38 @@ +package com.dnd.reevserver.domain.team.controller; + +import com.dnd.reevserver.domain.team.dto.request.AddTeamRequestDto; +import com.dnd.reevserver.domain.team.dto.response.TeamResponseDto; +import com.dnd.reevserver.domain.team.dto.response.AddTeamResponseDto; +import com.dnd.reevserver.domain.team.service.TeamService; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequestMapping("/api/v1/group") +@RequiredArgsConstructor +public class TeamController { + + private final TeamService groupService; + + @GetMapping("/list") + public ResponseEntity> getAllGroups(){ + List groups = groupService.getAllGroups(); + return ResponseEntity.ok().body(groups); + } + + @GetMapping("/{groupId}") + public ResponseEntity getGroupById(@PathVariable("groupId") Long groupId){ + TeamResponseDto group = groupService.getGroupById(groupId); + return ResponseEntity.ok().body(group); + } + + @PostMapping + public ResponseEntity addGroup(@RequestBody AddTeamRequestDto addGroupRequestDto){ + AddTeamResponseDto response = groupService.addGroup(addGroupRequestDto); + return ResponseEntity.ok().body(response); + } + +} diff --git a/src/main/java/com/dnd/reevserver/domain/team/dto/request/AddTeamRequestDto.java b/src/main/java/com/dnd/reevserver/domain/team/dto/request/AddTeamRequestDto.java new file mode 100644 index 0000000..ef30291 --- /dev/null +++ b/src/main/java/com/dnd/reevserver/domain/team/dto/request/AddTeamRequestDto.java @@ -0,0 +1,8 @@ +package com.dnd.reevserver.domain.team.dto.request; + +import lombok.Builder; + +@Builder +public record AddTeamRequestDto(String userId, String teamName, String description, + boolean isPublic, int maxNum) { +} diff --git a/src/main/java/com/dnd/reevserver/domain/team/dto/response/AddTeamResponseDto.java b/src/main/java/com/dnd/reevserver/domain/team/dto/response/AddTeamResponseDto.java new file mode 100644 index 0000000..dcdb3b4 --- /dev/null +++ b/src/main/java/com/dnd/reevserver/domain/team/dto/response/AddTeamResponseDto.java @@ -0,0 +1,7 @@ +package com.dnd.reevserver.domain.team.dto.response; + +import lombok.Builder; + +@Builder +public record AddTeamResponseDto(Long teamId) { +} diff --git a/src/main/java/com/dnd/reevserver/domain/team/dto/response/TeamResponseDto.java b/src/main/java/com/dnd/reevserver/domain/team/dto/response/TeamResponseDto.java new file mode 100644 index 0000000..ef39941 --- /dev/null +++ b/src/main/java/com/dnd/reevserver/domain/team/dto/response/TeamResponseDto.java @@ -0,0 +1,9 @@ +package com.dnd.reevserver.domain.team.dto.response; + +import lombok.Builder; + +@Builder +public record TeamResponseDto(Long teamId, String teamName, String description, + int userCount, String recentActString) { + +} diff --git a/src/main/java/com/dnd/reevserver/domain/team/entity/Team.java b/src/main/java/com/dnd/reevserver/domain/team/entity/Team.java new file mode 100644 index 0000000..c14da16 --- /dev/null +++ b/src/main/java/com/dnd/reevserver/domain/team/entity/Team.java @@ -0,0 +1,58 @@ +package com.dnd.reevserver.domain.team.entity; + +import com.dnd.reevserver.domain.userTeam.entity.UserTeam; +import jakarta.persistence.*; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; + +@Entity +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class Team { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long teamId; + + @Column(name = "team_name", nullable = false, length = 100) + private String teamName; + + @Column(nullable = false, length = 1000) + private String description; + + @Column(name = "is_public", nullable = false) + private Boolean isPublic; + + @Column(name = "max_num", nullable = false) + private int maxNum; + + @OneToMany(mappedBy = "team") + private List userTeams = new ArrayList<>(); + + @Column(name = "recent_act") + private LocalDateTime recentAct; + + @Column(name = "owner_id", nullable = false) + private String ownerId; + + @Builder + public Team(String teamName, String description, Boolean isPublic, int maxNum, String ownerId) { + this.teamName = teamName; + this.description = description; + this.isPublic = isPublic; + this.maxNum = maxNum; + this.recentAct = LocalDateTime.now(); + this.ownerId = ownerId; + } + + public void addUserTeam(UserTeam userTeam) { + userTeams.add(userTeam); + userTeam.setTeam(this); + } +} diff --git a/src/main/java/com/dnd/reevserver/domain/team/exception/TeamNotFoundException.java b/src/main/java/com/dnd/reevserver/domain/team/exception/TeamNotFoundException.java new file mode 100644 index 0000000..99134ad --- /dev/null +++ b/src/main/java/com/dnd/reevserver/domain/team/exception/TeamNotFoundException.java @@ -0,0 +1,17 @@ +package com.dnd.reevserver.domain.team.exception; + +import com.dnd.reevserver.global.exception.GeneralException; + +public class TeamNotFoundException extends GeneralException { + private static final String MESSAGE = "TeamId에 해당하는 모임이 존재하지 않습니다."; + + public TeamNotFoundException() { + super(MESSAGE); + } + + @Override + public int getStatusCode() { + return 404; + } + +} diff --git a/src/main/java/com/dnd/reevserver/domain/team/repository/TeamRepository.java b/src/main/java/com/dnd/reevserver/domain/team/repository/TeamRepository.java new file mode 100644 index 0000000..e72ea77 --- /dev/null +++ b/src/main/java/com/dnd/reevserver/domain/team/repository/TeamRepository.java @@ -0,0 +1,7 @@ +package com.dnd.reevserver.domain.team.repository; + +import com.dnd.reevserver.domain.team.entity.Team; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface TeamRepository extends JpaRepository { +} diff --git a/src/main/java/com/dnd/reevserver/domain/team/service/TeamService.java b/src/main/java/com/dnd/reevserver/domain/team/service/TeamService.java new file mode 100644 index 0000000..34f7b90 --- /dev/null +++ b/src/main/java/com/dnd/reevserver/domain/team/service/TeamService.java @@ -0,0 +1,92 @@ +package com.dnd.reevserver.domain.team.service; + +import com.dnd.reevserver.domain.team.dto.request.AddTeamRequestDto; +import com.dnd.reevserver.domain.team.dto.response.AddTeamResponseDto; +import com.dnd.reevserver.domain.team.dto.response.TeamResponseDto; +import com.dnd.reevserver.domain.team.entity.Team; +import com.dnd.reevserver.domain.team.exception.TeamNotFoundException; +import com.dnd.reevserver.domain.team.repository.TeamRepository; +import com.dnd.reevserver.domain.member.entity.Member; +import com.dnd.reevserver.domain.member.service.MemberService; +import com.dnd.reevserver.domain.userTeam.entity.UserTeam; +import com.dnd.reevserver.domain.userTeam.repository.UserTeamRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.List; + +@Service +@RequiredArgsConstructor +public class TeamService { + + private final TeamRepository teamRepository; + private final UserTeamRepository userTeamRepository; + private final MemberService memberService; + + @Transactional(readOnly = true) + public List getAllGroups() { + List groups = teamRepository.findAll(); + List teamList = groups.stream() + .map(team -> TeamResponseDto.builder() + .teamId(team.getTeamId()) + .teamName(team.getTeamName()) + .description(team.getDescription()) + .userCount(team.getUserTeams().size()) + .recentActString(getRecentActString(team.getRecentAct())) + .build()) + .toList(); + return teamList; + } + + @Transactional(readOnly = true) + public TeamResponseDto getGroupById(Long groupId) { + Team team = teamRepository.findById(groupId).orElseThrow(TeamNotFoundException::new); + return TeamResponseDto.builder() + .teamId(team.getTeamId()) + .teamName(team.getTeamName()) + .description(team.getDescription()) + .userCount(team.getUserTeams().size()) + .recentActString(getRecentActString(team.getRecentAct())) + .build(); + } + + private String getRecentActString(LocalDateTime recentAct){ + LocalDateTime now = LocalDateTime.now(); + long timeGap = ChronoUnit.MINUTES.between(recentAct, now); + + if(timeGap < 60){ + return timeGap + "분 전"; + } + if(timeGap < 1440){ + return ChronoUnit.HOURS.between(recentAct, now) + "시간 전"; + } + return ChronoUnit.DAYS.between(recentAct, now) + "일 전"; + + } + + + public AddTeamResponseDto addGroup(AddTeamRequestDto addTeamRequestDto) { + Team team = Team.builder().teamName(addTeamRequestDto.teamName()) + .description(addTeamRequestDto.description()) + .maxNum(addTeamRequestDto.maxNum()) + .ownerId(addTeamRequestDto.userId()) + .isPublic(addTeamRequestDto.isPublic()) + .build(); + + teamRepository.save(team); + Member member = memberService.findById(addTeamRequestDto.userId()); + UserTeam userTeam = new UserTeam(member,team); + userTeamRepository.save(userTeam); + + member.addUserGroup(userTeam); + team.addUserTeam(userTeam); + teamRepository.save(team); + userTeamRepository.save(userTeam); + + + return new AddTeamResponseDto(team.getTeamId()); + } +} diff --git a/src/main/java/com/dnd/reevserver/domain/template/dto/request/CreateTemplateRequestDto.java b/src/main/java/com/dnd/reevserver/domain/template/dto/request/CreateTemplateRequestDto.java index 3cb819e..1ed71e8 100644 --- a/src/main/java/com/dnd/reevserver/domain/template/dto/request/CreateTemplateRequestDto.java +++ b/src/main/java/com/dnd/reevserver/domain/template/dto/request/CreateTemplateRequestDto.java @@ -1,4 +1,6 @@ package com.dnd.reevserver.domain.template.dto.request; + public record CreateTemplateRequestDto(String userId, String templateName, String content, String description) { + } diff --git a/src/main/java/com/dnd/reevserver/domain/userTeam/entity/UserTeam.java b/src/main/java/com/dnd/reevserver/domain/userTeam/entity/UserTeam.java new file mode 100644 index 0000000..20fcdc1 --- /dev/null +++ b/src/main/java/com/dnd/reevserver/domain/userTeam/entity/UserTeam.java @@ -0,0 +1,41 @@ +package com.dnd.reevserver.domain.userTeam.entity; + +import com.dnd.reevserver.domain.team.entity.Team; +import com.dnd.reevserver.domain.member.entity.Member; +import jakarta.persistence.*; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Entity +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Table(name = "user_team") +public class UserTeam { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long userTeamId; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "user_id", nullable = false) + private Member member; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "team_id", nullable = false) + private Team team; + + public void setMember(Member member) { + this.member = member; + } + + public void setTeam(Team team) { + this.team = team; + } + + public UserTeam(Member member, Team team) { + this.member = member; + this.team = team; + } + +} diff --git a/src/main/java/com/dnd/reevserver/domain/userTeam/repository/UserTeamRepository.java b/src/main/java/com/dnd/reevserver/domain/userTeam/repository/UserTeamRepository.java new file mode 100644 index 0000000..988d0cd --- /dev/null +++ b/src/main/java/com/dnd/reevserver/domain/userTeam/repository/UserTeamRepository.java @@ -0,0 +1,7 @@ +package com.dnd.reevserver.domain.userTeam.repository; + +import com.dnd.reevserver.domain.userTeam.entity.UserTeam; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface UserTeamRepository extends JpaRepository { +}