diff --git a/src/main/java/likelion/MZConnent/api/club/MyClubController.java b/src/main/java/likelion/MZConnent/api/club/MyClubController.java index 5d05380..e711a49 100644 --- a/src/main/java/likelion/MZConnent/api/club/MyClubController.java +++ b/src/main/java/likelion/MZConnent/api/club/MyClubController.java @@ -14,6 +14,8 @@ import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.web.bind.annotation.*; +import java.util.Map; + @Slf4j @RequiredArgsConstructor @RestController @@ -46,4 +48,21 @@ public ResponseEntity getMemberRateAndCount(@AuthenticationP return ResponseEntity.ok(response); } + @PostMapping("/api/clubs/{clubId}/close") + public ResponseEntity closeClub(@AuthenticationPrincipal UserPrinciple userPrinciple, @PathVariable Long clubId) { + myClubService.closeClub(userPrinciple.getEmail(), clubId); + return ResponseEntity.ok(Map.of("messege","모임 마감 성공")); + } + + @DeleteMapping("/api/clubs/{clubId}/members/{memberId}") + public ResponseEntity deleteMember(@AuthenticationPrincipal UserPrinciple userPrinciple, @PathVariable Long clubId, @PathVariable Long memberId) { + myClubService.deleteClubMember(userPrinciple.getEmail(), clubId, memberId); + return ResponseEntity.ok(Map.of("messege","멤버 추방 성공")); + } + + @PostMapping("/api/clubs/{clubId}/leave") + public ResponseEntity leaveClub(@AuthenticationPrincipal UserPrinciple userPrinciple, @PathVariable Long clubId) { + myClubService.leaveClub(userPrinciple.getEmail(), clubId); + return ResponseEntity.ok(Map.of("messege","모임 탈퇴 성공")); + } } diff --git a/src/main/java/likelion/MZConnent/domain/manner/Manner.java b/src/main/java/likelion/MZConnent/domain/manner/Manner.java index fca4251..befdedc 100644 --- a/src/main/java/likelion/MZConnent/domain/manner/Manner.java +++ b/src/main/java/likelion/MZConnent/domain/manner/Manner.java @@ -9,9 +9,11 @@ import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; +import lombok.Setter; @Entity @Getter +@Setter @NoArgsConstructor public class Manner { @Id @@ -26,7 +28,7 @@ public class Manner { private Member member; @ManyToOne - @JoinColumn(name = "clubMemberId", nullable = false) + @JoinColumn(name = "clubMemberId", nullable = true) private ClubMember clubMember; @Builder diff --git a/src/main/java/likelion/MZConnent/repository/manner/MannerRepository.java b/src/main/java/likelion/MZConnent/repository/manner/MannerRepository.java index 29a4a3e..9a6b0e0 100644 --- a/src/main/java/likelion/MZConnent/repository/manner/MannerRepository.java +++ b/src/main/java/likelion/MZConnent/repository/manner/MannerRepository.java @@ -7,9 +7,11 @@ import org.springframework.stereotype.Repository; import java.util.List; +import java.util.Map; @Repository public interface MannerRepository extends JpaRepository { long countByMemberAndClubMember(Member member, ClubMember clubMember); List findByMember(Member member); + List findByClubMember(ClubMember targetClubMember); } diff --git a/src/main/java/likelion/MZConnent/service/club/ClubInfoService.java b/src/main/java/likelion/MZConnent/service/club/ClubInfoService.java index 83b10c7..cf5d7d1 100644 --- a/src/main/java/likelion/MZConnent/service/club/ClubInfoService.java +++ b/src/main/java/likelion/MZConnent/service/club/ClubInfoService.java @@ -1,5 +1,6 @@ package likelion.MZConnent.service.club; +import jakarta.transaction.Transactional; import likelion.MZConnent.domain.club.ClubRole; import likelion.MZConnent.domain.member.Member; import likelion.MZConnent.dto.club.LeaderDto; @@ -21,6 +22,7 @@ @Slf4j @Service +@Transactional @RequiredArgsConstructor public class ClubInfoService { private final ClubRepository clubRepository; diff --git a/src/main/java/likelion/MZConnent/service/club/MyClubService.java b/src/main/java/likelion/MZConnent/service/club/MyClubService.java index 6299c06..62e18c0 100644 --- a/src/main/java/likelion/MZConnent/service/club/MyClubService.java +++ b/src/main/java/likelion/MZConnent/service/club/MyClubService.java @@ -1,10 +1,17 @@ package likelion.MZConnent.service.club; +import jakarta.transaction.Transactional; import likelion.MZConnent.domain.club.Club; +import likelion.MZConnent.domain.club.ClubMember; +import likelion.MZConnent.domain.club.ClubRole; +import likelion.MZConnent.domain.manner.Manner; import likelion.MZConnent.domain.member.Member; import likelion.MZConnent.dto.club.SelfIntroductionDto; import likelion.MZConnent.dto.club.response.MyClubDetailResponse; import likelion.MZConnent.dto.club.response.MyClubSimpleResponse; +import likelion.MZConnent.repository.club.ClubMemberRepository; +import likelion.MZConnent.repository.club.ClubRepository; +import likelion.MZConnent.repository.manner.MannerRepository; import likelion.MZConnent.repository.member.MemberRepository; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -15,9 +22,13 @@ @Service @RequiredArgsConstructor +@Transactional @Slf4j public class MyClubService { private final MemberRepository memberRepository; + private final ClubRepository clubRepository; + private final ClubMemberRepository clubMemberRepository; + private final MannerRepository mannerRepository; public MyClubSimpleResponse getMyClubs(String email) { Member member = getMemberByEmail(email); @@ -32,23 +43,6 @@ public MyClubSimpleResponse getMyClubs(String email) { .build(); } - private List getClubsByMember(Member member) { - return member.getClubMembers().stream() - .map(cm -> cm.getClub()) - .collect(Collectors.toList()); - } - - private MyClubSimpleResponse.MyClubSimpleDto convertToSimpleDto(Club club) { - return MyClubSimpleResponse.MyClubSimpleDto.builder() - .clubId(club.getClubId()) - .title(club.getTitle()) - .cultureName(club.getCulture().getName()) - .meetingDate(club.getMeetingDate()) - .currentParticipant(club.getClubMembers().size()) - .maxParticipant(club.getMaxParticipant()) - .build(); - } - public MyClubDetailResponse getMyClubDetail(String email, Long clubId) { Member member = getMemberByEmail(email); Club club = getClubByMemberAndId(member, clubId); @@ -67,6 +61,82 @@ public MyClubDetailResponse getMyClubDetail(String email, Long clubId) { .build(); } + public void closeClub(String email, Long clubId) { + Member member = getMemberByEmail(email); + ClubMember clubMember = getClubMemberByMemberAndId(member, clubId); + Club club = clubRepository.findById(clubId) + .orElseThrow(() -> new IllegalArgumentException("해당 클럽을 찾을 수 없습니다.")); + + // 클럽장이 아닌 경우 예외 처리 + if (!clubMember.getClubRole().equals(ClubRole.LEADER)){ + throw new IllegalArgumentException("클럽장만 클럽을 종료할 수 있습니다."); + } + + club.setStatus("CLOSE"); + clubRepository.save(club); + } + + public void deleteClubMember(String email, Long clubId, Long targetMemberId) { + Member member = getMemberByEmail(email); + Club club = getClubById(clubId); + Member targetMember = memberRepository.findById(targetMemberId) + .orElseThrow(() -> new IllegalArgumentException("해당 멤버를 찾을 수 없습니다.")); + + ClubMember clubMember = getClubMemberByMemberAndId(member, clubId); + ClubMember targetClubMember = getClubMemberByMemberAndId(targetMember, clubId); + + // 클럽장이 아닌 경우 예외 처리 + if (!clubMember.getClubRole().equals(ClubRole.LEADER)){ + throw new IllegalArgumentException("클럽장만 멤버를 삭제할 수 있습니다."); + } + + // 해당 클럽 멤버와 관련된 manner 엔티티의 clubMember 필드를 null로 설정 + List manners = mannerRepository.findByClubMember(targetClubMember); + manners.forEach(manner -> manner.setClubMember(null)); + mannerRepository.saveAll(manners); + + clubMemberRepository.delete(targetClubMember); + club.setCurrentParticipant(club.getCurrentParticipant() - 1); + clubRepository.save(club); + } + + public void leaveClub(String email, Long clubId) { + Member member = getMemberByEmail(email); + Club club = getClubById(clubId); + ClubMember clubMember = getClubMemberByMemberAndId(member, clubId); + + // 클럽장인 경우 예외 처리 + if (clubMember.getClubRole().equals(ClubRole.LEADER)){ + throw new IllegalArgumentException("클럽장은 클럽을 탈퇴할 수 없습니다."); + } + + // 해당 클럽 멤버와 관련된 manner 엔티티의 clubMember 필드를 null로 설정 + List manners = mannerRepository.findByClubMember(clubMember); + manners.forEach(manner -> manner.setClubMember(null)); + mannerRepository.saveAll(manners); + + clubMemberRepository.delete(clubMember); + club.setCurrentParticipant(club.getCurrentParticipant() - 1); + clubRepository.save(club); + } + + private List getClubsByMember(Member member) { + return member.getClubMembers().stream() + .map(ClubMember::getClub) + .collect(Collectors.toList()); + } + + private MyClubSimpleResponse.MyClubSimpleDto convertToSimpleDto(Club club) { + return MyClubSimpleResponse.MyClubSimpleDto.builder() + .clubId(club.getClubId()) + .title(club.getTitle()) + .cultureName(club.getCulture().getName()) + .meetingDate(club.getMeetingDate()) + .currentParticipant(club.getClubMembers().size()) + .maxParticipant(club.getMaxParticipant()) + .build(); + } + private Member getMemberByEmail(String email) { return memberRepository.findByEmail(email) .orElseThrow(() -> new IllegalArgumentException("존재하지 않는 사용자입니다.")); @@ -74,7 +144,7 @@ private Member getMemberByEmail(String email) { private Club getClubByMemberAndId(Member member, Long clubId) { return member.getClubMembers().stream() - .map(cm -> cm.getClub()) + .map(ClubMember::getClub) .filter(c -> c.getClubId().equals(clubId)) .findFirst() .orElseThrow(() -> new IllegalArgumentException("해당 클럽을 찾을 수 없습니다.")); @@ -105,4 +175,16 @@ private List convertToMemberDtos(Club club .build()) .collect(Collectors.toList()); } + + private ClubMember getClubMemberByMemberAndId(Member member, Long clubId) { + return member.getClubMembers().stream() + .filter(cm -> cm.getClub().getClubId().equals(clubId)) + .findFirst() + .orElseThrow(() -> new IllegalArgumentException("해당 멤버가 가입된 모임이 아닙니다.")); + } + + private Club getClubById(Long clubId) { + return clubRepository.findById(clubId) + .orElseThrow(() -> new IllegalArgumentException("존재하지 않는 모임입니다.")); + } } diff --git a/src/main/java/likelion/MZConnent/service/club/RegionCategoryService.java b/src/main/java/likelion/MZConnent/service/club/RegionCategoryService.java index 325a936..c4e2b8e 100644 --- a/src/main/java/likelion/MZConnent/service/club/RegionCategoryService.java +++ b/src/main/java/likelion/MZConnent/service/club/RegionCategoryService.java @@ -1,5 +1,6 @@ package likelion.MZConnent.service.club; +import jakarta.transaction.Transactional; import likelion.MZConnent.domain.club.RegionCategory; import likelion.MZConnent.dto.club.RegionCategoryDto; import likelion.MZConnent.dto.club.response.RegionCategoryResponse; @@ -12,6 +13,7 @@ @Service @RequiredArgsConstructor +@Transactional public class RegionCategoryService { private final RegionCategoryRepository regionCategoryRepository; diff --git a/src/main/java/likelion/MZConnent/service/review/ReviewService.java b/src/main/java/likelion/MZConnent/service/review/ReviewService.java index 072fecc..93cdd4d 100644 --- a/src/main/java/likelion/MZConnent/service/review/ReviewService.java +++ b/src/main/java/likelion/MZConnent/service/review/ReviewService.java @@ -1,5 +1,6 @@ package likelion.MZConnent.service.review; +import jakarta.transaction.Transactional; import likelion.MZConnent.domain.culture.Culture; import likelion.MZConnent.domain.member.Member; import likelion.MZConnent.domain.review.Review; @@ -29,6 +30,7 @@ @Service @Slf4j @RequiredArgsConstructor +@Transactional public class ReviewService { private final ReviewRepository reviewRepository; private final S3ImageService s3ImageService;