Skip to content

Commit 2d95888

Browse files
authored
Merge pull request #48 from Sportize/feat/notification
๐Ÿ› Fix: users - club ์—ฐ๊ด€๊ด€๊ณ„ ์˜ค๋ฅ˜ ์ˆ˜์ •
2 parents c743f9a + e05a202 commit 2d95888

6 files changed

Lines changed: 152 additions & 10 deletions

File tree

โ€Žsrc/main/java/com/be/sportizebe/domain/club/dto/request/ClubCreateRequest.javaโ€Ž

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import com.be.sportizebe.domain.club.entity.Club;
44
import com.be.sportizebe.domain.user.entity.SportType;
5-
import com.be.sportizebe.domain.user.entity.User;
65
import io.swagger.v3.oas.annotations.media.Schema;
76
import jakarta.validation.constraints.NotBlank;
87

@@ -13,14 +12,13 @@ public record ClubCreateRequest(
1312
@Schema(description = "๋™ํ˜ธํšŒ ๊ด€๋ จ ์ข…๋ชฉ", example = "SOCCER") SportType clubType,
1413
@Schema(description = "์ตœ๋Œ€ ์ •์›", example = "20") Integer maxMembers) {
1514

16-
public Club toEntity(User user, String clubImage) {
15+
public Club toEntity(String clubImage) {
1716
return Club.builder()
1817
.name(name)
1918
.introduce(introduce)
2019
.clubType(clubType)
2120
.maxMembers(maxMembers)
2221
.clubImage(clubImage)
23-
.leader(user)
2422
.build();
2523
}
2624
}

โ€Žsrc/main/java/com/be/sportizebe/domain/club/entity/Club.javaโ€Ž

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,17 +39,40 @@ public class Club extends BaseTimeEntity {
3939

4040
private String clubImage; // ๋™ํ˜ธํšŒ ์‚ฌ์ง„ URL
4141

42-
@ManyToOne(fetch = FetchType.LAZY)
43-
@JoinColumn(name = "leader_id", nullable = false)
44-
private User leader; // ๋™ํ˜ธํšŒ์žฅ
45-
4642
@OneToOne(mappedBy = "club", fetch = FetchType.LAZY)
4743
private ChatRoom chatRoom; // ๋™ํ˜ธํšŒ ์ฑ„ํŒ…๋ฐฉ
4844

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

49+
/**
50+
* ๋™ํ˜ธํšŒ์žฅ(LEADER) ์กฐํšŒ
51+
* ClubMember์—์„œ LEADER ์—ญํ• ์„ ๊ฐ€์ง„ ๋ฉค๋ฒ„๋ฅผ ์ฐพ์•„ ๋ฐ˜ํ™˜
52+
*/
53+
public ClubMember getLeaderMember() {
54+
return members.stream()
55+
.filter(member -> member.getRole() == ClubMember.ClubRole.LEADER)
56+
.findFirst()
57+
.orElse(null);
58+
}
59+
60+
/**
61+
* ๋™ํ˜ธํšŒ์žฅ User ์กฐํšŒ
62+
*/
63+
public User getLeader() {
64+
ClubMember leaderMember = getLeaderMember();
65+
return leaderMember != null ? leaderMember.getUser() : null;
66+
}
67+
68+
/**
69+
* ํŠน์ • ์‚ฌ์šฉ์ž๊ฐ€ ๋™ํ˜ธํšŒ์žฅ์ธ์ง€ ํ™•์ธ
70+
*/
71+
public boolean isLeader(Long userId) {
72+
ClubMember leaderMember = getLeaderMember();
73+
return leaderMember != null && leaderMember.getUser().getId() == userId;
74+
}
75+
5376
public void update(String name, String introduce, Integer maxMembers, SportType clubType) {
5477
this.name = name;
5578
this.introduce = introduce;

โ€Žsrc/main/java/com/be/sportizebe/domain/club/service/ClubServiceImpl.javaโ€Ž

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ public ClubResponse createClub(ClubCreateRequest request, MultipartFile image, L
4949
}
5050

5151
// ๋™ํ˜ธํšŒ ์—”ํ‹ฐํ‹ฐ ์ƒ์„ฑ
52-
Club club = request.toEntity(user, clubImageUrl);
52+
Club club = request.toEntity(clubImageUrl);
5353
clubRepository.save(club);
5454

5555
// ๋™ํ˜ธํšŒ ๋ฉค๋ฒ„ ํ…Œ์ด๋ธ”์— ๋ฐฉ์žฅ(๋™ํ˜ธํšŒ ์ƒ์„ฑ์ž) ์ถ”๊ฐ€
@@ -58,6 +58,7 @@ public ClubResponse createClub(ClubCreateRequest request, MultipartFile image, L
5858
.user(user)
5959
.role(ClubMember.ClubRole.LEADER)
6060
.build();
61+
club.getMembers().add(leaderMember);
6162
clubMemberRepository.save(leaderMember);
6263

6364
// ๋™ํ˜ธํšŒ ๋‹จ์ฒด ์ฑ„ํŒ…๋ฐฉ ์ƒ์„ฑ
@@ -73,7 +74,7 @@ public ClubResponse updateClub(Long clubId, ClubUpdateRequest request, Long user
7374
.orElseThrow(() -> new CustomException(ClubErrorCode.CLUB_NOT_FOUND));
7475

7576
// ๋™ํ˜ธํšŒ ๋ฐฉ์žฅ๋งŒ ์ˆ˜์ • ๊ฐ€๋Šฅํ•˜๋„๋ก ๊ฒ€์ฆ
76-
if (club.getLeader().getId() != userId) {
77+
if (!club.isLeader(userId)) {
7778
throw new CustomException(ClubErrorCode.CLUB_UPDATE_DENIED);
7879
}
7980

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

99100
// ๋™ํ˜ธํšŒ ๋ฐฉ์žฅ๋งŒ ์ˆ˜์ • ๊ฐ€๋Šฅํ•˜๋„๋ก ๊ฒ€์ฆ
100-
if (club.getLeader().getId() != userId) {
101+
if (!club.isLeader(userId)) {
101102
throw new CustomException(ClubErrorCode.CLUB_UPDATE_DENIED);
102103
}
103104

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package com.be.sportizebe.domain.notification.entity;
2+
3+
import com.be.sportizebe.domain.club.entity.Club;
4+
import com.be.sportizebe.domain.user.entity.User;
5+
import com.be.sportizebe.global.common.BaseTimeEntity;
6+
import jakarta.persistence.*;
7+
import lombok.AllArgsConstructor;
8+
import lombok.Builder;
9+
import lombok.Getter;
10+
import lombok.NoArgsConstructor;
11+
12+
@Entity
13+
@Getter
14+
@Builder
15+
@AllArgsConstructor
16+
@NoArgsConstructor
17+
@Table(name = "join_club_request", uniqueConstraints = {
18+
@UniqueConstraint(columnNames = {"user_id", "club_id"})
19+
})
20+
public class JoinClubRequest extends BaseTimeEntity {
21+
22+
public enum JoinClubRequestStatus {
23+
PENDING, // ๋Œ€๊ธฐ
24+
ACCEPTED, // ์Šน์ธ
25+
REJECTED // ๊ฑฐ์ ˆ
26+
}
27+
28+
@Id
29+
@GeneratedValue(strategy = GenerationType.IDENTITY)
30+
private Long id;
31+
32+
@ManyToOne(fetch = FetchType.LAZY)
33+
@JoinColumn(name = "user_id", nullable = false)
34+
private User user; // ๊ฐ€์ž… ์‹ ์ฒญ์ž
35+
36+
@ManyToOne(fetch = FetchType.LAZY)
37+
@JoinColumn(name = "club_id", nullable = false)
38+
private Club club; // ๊ฐ€์ž… ์‹ ์ฒญ ๋Œ€์ƒ ๋™ํ˜ธํšŒ
39+
40+
@Enumerated(EnumType.STRING)
41+
@Column(nullable = false)
42+
@Builder.Default
43+
private JoinClubRequestStatus status = JoinClubRequestStatus.PENDING;
44+
45+
// ๊ฐ€์ž… ์Šน์ธ ์‹œ ์ƒํƒœ ๋ณ€๊ฒฝ
46+
public void accept() {
47+
this.status = JoinClubRequestStatus.ACCEPTED;
48+
}
49+
50+
// ๊ฐ€์ž… ๊ฑฐ์ ˆ ์‹œ ์ƒํƒœ ๋ณ€๊ฒฝ
51+
public void reject() {
52+
this.status = JoinClubRequestStatus.REJECTED;
53+
}
54+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package com.be.sportizebe.domain.notification.entity;
2+
3+
import com.be.sportizebe.domain.user.entity.User;
4+
import com.be.sportizebe.global.common.BaseTimeEntity;
5+
import jakarta.persistence.*;
6+
import lombok.AllArgsConstructor;
7+
import lombok.Builder;
8+
import lombok.Getter;
9+
import lombok.NoArgsConstructor;
10+
11+
@Entity
12+
@Getter
13+
@Builder
14+
@AllArgsConstructor
15+
@NoArgsConstructor
16+
@Table(name = "notifications", indexes = {
17+
@Index(name = "idx_notification_receiver", columnList = "receiver_id"),
18+
@Index(name = "idx_notification_is_read", columnList = "receiver_id, is_read")
19+
})
20+
public class Notification extends BaseTimeEntity {
21+
22+
public enum NotificationType {
23+
JOIN_REQUEST, // ๊ฐ€์ž… ์‹ ์ฒญ (๋™ํ˜ธํšŒ์žฅ์—๊ฒŒ)
24+
JOIN_APPROVED, // ๊ฐ€์ž… ์Šน์ธ (์‹ ์ฒญ์ž์—๊ฒŒ)
25+
JOIN_REJECTED, // ๊ฐ€์ž… ๊ฑฐ์ ˆ (์‹ ์ฒญ์ž์—๊ฒŒ)
26+
CHAT, // ์ƒˆ ์ฑ„ํŒ… ๋ฉ”์‹œ์ง€
27+
COMMENT // ์ƒˆ ๋Œ“๊ธ€
28+
}
29+
30+
@Id
31+
@GeneratedValue(strategy = GenerationType.IDENTITY)
32+
private Long id;
33+
34+
@ManyToOne(fetch = FetchType.LAZY)
35+
@JoinColumn(name = "receiver_id", nullable = false)
36+
private User receiver; // ์•Œ๋ฆผ ์ˆ˜์‹ ์ž
37+
38+
@Enumerated(EnumType.STRING)
39+
@Column(nullable = false)
40+
private NotificationType type;
41+
42+
@Column(nullable = false)
43+
private String message; // ์•Œ๋ฆผ ๋ฉ”์‹œ์ง€
44+
45+
@Column(nullable = false)
46+
@Builder.Default
47+
private Boolean isRead = false;
48+
49+
// ๊ฐ€์ž… ์‹ ์ฒญ ๊ด€๋ จ ์•Œ๋ฆผ์šฉ (JOIN_REQUEST, JOIN_APPROVED, JOIN_REJECTED)
50+
@ManyToOne(fetch = FetchType.LAZY)
51+
@JoinColumn(name = "join_request_id")
52+
private JoinClubRequest joinClubRequest;
53+
54+
// ๋Œ“๊ธ€ ์•Œ๋ฆผ์šฉ - targetId์™€ targetType์œผ๋กœ ๋‹คํ˜•์„ฑ ์ฒ˜๋ฆฌ
55+
// COMMENT: postId, CHAT: chatRoomId ๋“ฑ
56+
private Long targetId;
57+
58+
public void markAsRead() {
59+
this.isRead = true;
60+
}
61+
}

โ€Žsrc/main/java/com/be/sportizebe/domain/user/entity/User.javaโ€Ž

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.be.sportizebe.domain.user.entity;
22

3+
import com.be.sportizebe.domain.club.entity.ClubMember;
34
import com.be.sportizebe.domain.post.entity.Post;
45
import com.be.sportizebe.global.common.BaseTimeEntity;
56
import com.fasterxml.jackson.annotation.JsonIgnore;
@@ -62,6 +63,10 @@ public class User extends BaseTimeEntity {
6263
@Builder.Default
6364
private List<Post> posts = new ArrayList<>(); // ์ž‘์„ฑํ•œ ๊ฒŒ์‹œ๊ธ€ ๋ชฉ๋ก
6465

66+
@OneToMany(mappedBy = "user")
67+
@Builder.Default
68+
private List<ClubMember> clubMemberships = new ArrayList<>(); // ๊ฐ€์ž…ํ•œ ๋™ํ˜ธํšŒ ๋ชฉ๋ก
69+
6570
public void updateRefreshToken(String refreshToken) {
6671
this.refreshToken = refreshToken;
6772
}

0 commit comments

Comments
ย (0)