Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import com.be.sportizebe.domain.club.entity.Club;
import com.be.sportizebe.domain.user.entity.SportType;
import com.be.sportizebe.domain.user.entity.User;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;

Expand All @@ -13,14 +12,13 @@ public record ClubCreateRequest(
@Schema(description = "λ™ν˜ΈνšŒ κ΄€λ ¨ μ’…λͺ©", example = "SOCCER") SportType clubType,
@Schema(description = "μ΅œλŒ€ 정원", example = "20") Integer maxMembers) {

public Club toEntity(User user, String clubImage) {
public Club toEntity(String clubImage) {
return Club.builder()
.name(name)
.introduce(introduce)
.clubType(clubType)
.maxMembers(maxMembers)
.clubImage(clubImage)
.leader(user)
.build();
}
}
31 changes: 27 additions & 4 deletions src/main/java/com/be/sportizebe/domain/club/entity/Club.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,17 +39,40 @@ public class Club extends BaseTimeEntity {

private String clubImage; // λ™ν˜ΈνšŒ 사진 URL

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "leader_id", nullable = false)
private User leader; // λ™ν˜ΈνšŒμž₯

@OneToOne(mappedBy = "club", fetch = FetchType.LAZY)
private ChatRoom chatRoom; // λ™ν˜ΈνšŒ μ±„νŒ…λ°©

@OneToMany(mappedBy = "club", cascade = CascadeType.ALL, orphanRemoval = true)
@Builder.Default
private List<ClubMember> members = new ArrayList<>();

/**
* λ™ν˜ΈνšŒμž₯(LEADER) 쑰회
* ClubMemberμ—μ„œ LEADER 역할을 κ°€μ§„ 멀버λ₯Ό μ°Ύμ•„ λ°˜ν™˜
*/
public ClubMember getLeaderMember() {
return members.stream()
.filter(member -> member.getRole() == ClubMember.ClubRole.LEADER)
.findFirst()
.orElse(null);
}

/**
* λ™ν˜ΈνšŒμž₯ User 쑰회
*/
public User getLeader() {
ClubMember leaderMember = getLeaderMember();
return leaderMember != null ? leaderMember.getUser() : null;
}

/**
* νŠΉμ • μ‚¬μš©μžκ°€ λ™ν˜ΈνšŒμž₯인지 확인
*/
public boolean isLeader(Long userId) {
ClubMember leaderMember = getLeaderMember();
return leaderMember != null && leaderMember.getUser().getId() == userId;
}

public void update(String name, String introduce, Integer maxMembers, SportType clubType) {
this.name = name;
this.introduce = introduce;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public ClubResponse createClub(ClubCreateRequest request, MultipartFile image, L
}

// λ™ν˜ΈνšŒ μ—”ν‹°ν‹° 생성
Club club = request.toEntity(user, clubImageUrl);
Club club = request.toEntity(clubImageUrl);
clubRepository.save(club);

// λ™ν˜ΈνšŒ 멀버 ν…Œμ΄λΈ”μ— λ°©μž₯(λ™ν˜ΈνšŒ μƒμ„±μž) μΆ”κ°€
Expand All @@ -58,6 +58,7 @@ public ClubResponse createClub(ClubCreateRequest request, MultipartFile image, L
.user(user)
.role(ClubMember.ClubRole.LEADER)
.build();
club.getMembers().add(leaderMember);
clubMemberRepository.save(leaderMember);

// λ™ν˜ΈνšŒ 단체 μ±„νŒ…λ°© 생성
Expand All @@ -73,7 +74,7 @@ public ClubResponse updateClub(Long clubId, ClubUpdateRequest request, Long user
.orElseThrow(() -> new CustomException(ClubErrorCode.CLUB_NOT_FOUND));

// λ™ν˜ΈνšŒ λ°©μž₯만 μˆ˜μ • κ°€λŠ₯ν•˜λ„λ‘ 검증
if (club.getLeader().getId() != userId) {
if (!club.isLeader(userId)) {
throw new CustomException(ClubErrorCode.CLUB_UPDATE_DENIED);
}

Expand All @@ -97,7 +98,7 @@ public ClubImageResponse updateClubImage(Long clubId, MultipartFile image, Long
.orElseThrow(() -> new CustomException(ClubErrorCode.CLUB_NOT_FOUND));

// λ™ν˜ΈνšŒ λ°©μž₯만 μˆ˜μ • κ°€λŠ₯ν•˜λ„λ‘ 검증
if (club.getLeader().getId() != userId) {
if (!club.isLeader(userId)) {
throw new CustomException(ClubErrorCode.CLUB_UPDATE_DENIED);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package com.be.sportizebe.domain.notification.entity;

import com.be.sportizebe.domain.club.entity.Club;
import com.be.sportizebe.domain.user.entity.User;
import com.be.sportizebe.global.common.BaseTimeEntity;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Entity
@Getter
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Table(name = "join_club_request", uniqueConstraints = {
@UniqueConstraint(columnNames = {"user_id", "club_id"})
})
public class JoinClubRequest extends BaseTimeEntity {

public enum JoinClubRequestStatus {
PENDING, // λŒ€κΈ°
ACCEPTED, // 승인
REJECTED // 거절
}

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id", nullable = false)
private User user; // κ°€μž… μ‹ μ²­μž

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "club_id", nullable = false)
private Club club; // κ°€μž… μ‹ μ²­ λŒ€μƒ λ™ν˜ΈνšŒ

@Enumerated(EnumType.STRING)
@Column(nullable = false)
@Builder.Default
private JoinClubRequestStatus status = JoinClubRequestStatus.PENDING;

// κ°€μž… 승인 μ‹œ μƒνƒœ λ³€κ²½
public void accept() {
this.status = JoinClubRequestStatus.ACCEPTED;
}

// κ°€μž… 거절 μ‹œ μƒνƒœ λ³€κ²½
public void reject() {
this.status = JoinClubRequestStatus.REJECTED;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package com.be.sportizebe.domain.notification.entity;

import com.be.sportizebe.domain.user.entity.User;
import com.be.sportizebe.global.common.BaseTimeEntity;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Entity
@Getter
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Table(name = "notifications", indexes = {
@Index(name = "idx_notification_receiver", columnList = "receiver_id"),
@Index(name = "idx_notification_is_read", columnList = "receiver_id, is_read")
})
public class Notification extends BaseTimeEntity {

public enum NotificationType {
JOIN_REQUEST, // κ°€μž… μ‹ μ²­ (λ™ν˜ΈνšŒμž₯μ—κ²Œ)
JOIN_APPROVED, // κ°€μž… 승인 (μ‹ μ²­μžμ—κ²Œ)
JOIN_REJECTED, // κ°€μž… 거절 (μ‹ μ²­μžμ—κ²Œ)
CHAT, // μƒˆ μ±„νŒ… λ©”μ‹œμ§€
COMMENT // μƒˆ λŒ“κΈ€
}

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "receiver_id", nullable = false)
private User receiver; // μ•Œλ¦Ό μˆ˜μ‹ μž

@Enumerated(EnumType.STRING)
@Column(nullable = false)
private NotificationType type;

@Column(nullable = false)
private String message; // μ•Œλ¦Ό λ©”μ‹œμ§€

@Column(nullable = false)
@Builder.Default
private Boolean isRead = false;

// κ°€μž… μ‹ μ²­ κ΄€λ ¨ μ•Œλ¦Όμš© (JOIN_REQUEST, JOIN_APPROVED, JOIN_REJECTED)
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "join_request_id")
private JoinClubRequest joinClubRequest;

// λŒ“κΈ€ μ•Œλ¦Όμš© - targetId와 targetType으둜 λ‹€ν˜•μ„± 처리
// COMMENT: postId, CHAT: chatRoomId λ“±
private Long targetId;

public void markAsRead() {
this.isRead = true;
}
}
5 changes: 5 additions & 0 deletions src/main/java/com/be/sportizebe/domain/user/entity/User.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.be.sportizebe.domain.user.entity;

import com.be.sportizebe.domain.club.entity.ClubMember;
import com.be.sportizebe.domain.post.entity.Post;
import com.be.sportizebe.global.common.BaseTimeEntity;
import com.fasterxml.jackson.annotation.JsonIgnore;
Expand Down Expand Up @@ -62,6 +63,10 @@ public class User extends BaseTimeEntity {
@Builder.Default
private List<Post> posts = new ArrayList<>(); // μž‘μ„±ν•œ κ²Œμ‹œκΈ€ λͺ©λ‘

@OneToMany(mappedBy = "user")
@Builder.Default
private List<ClubMember> clubMemberships = new ArrayList<>(); // κ°€μž…ν•œ λ™ν˜ΈνšŒ λͺ©λ‘

public void updateRefreshToken(String refreshToken) {
this.refreshToken = refreshToken;
}
Expand Down