Skip to content

Commit 8471a96

Browse files
안훈기안훈기
authored andcommitted
⏺✨ Feat: 매칭 취소 및 재참여 기능
1 parent b6a9a45 commit 8471a96

File tree

12 files changed

+110
-6
lines changed

12 files changed

+110
-6
lines changed

src/main/java/com/be/sportizebe/domain/match/controller/MatchController.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import org.springframework.http.HttpStatus;
2020
import org.springframework.http.ResponseEntity;
2121
import org.springframework.security.core.annotation.AuthenticationPrincipal;
22+
import org.springframework.web.bind.annotation.DeleteMapping;
2223
import org.springframework.web.bind.annotation.GetMapping;
2324
import org.springframework.web.bind.annotation.ModelAttribute;
2425
import org.springframework.web.bind.annotation.PathVariable;
@@ -68,6 +69,16 @@ public ResponseEntity<BaseResponse<MatchDetailResponse>> getMatchDetail(
6869
return ResponseEntity.ok(BaseResponse.success("매칭 상세 조회 성공", response));
6970
}
7071

72+
@Operation(summary = "매칭 취소")
73+
@DeleteMapping("/{matchId}/leave")
74+
public ResponseEntity<BaseResponse<Void>> leaveMatch(
75+
@PathVariable Long matchId,
76+
@AuthenticationPrincipal UserAuthInfo userAuthInfo
77+
) {
78+
matchService.leaveMatch(matchId, userAuthInfo.getId());
79+
return ResponseEntity.ok(BaseResponse.success("매칭 취소 성공", null));
80+
}
81+
7182
@Operation(summary = "내 주변 매칭 목록 조회", description = "매칭상태가 OPEN인 매칭들만 보여준다.")
7283
@GetMapping("/near")
7384
public ResponseEntity<BaseResponse<List<MatchNearResponse>>> getNearMatches(

src/main/java/com/be/sportizebe/domain/match/dto/request/MatchCreateRequest.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,13 @@ public record MatchCreateRequest(
1616

1717
@Schema(description = "최대 참여 인원 수", example = "10")
1818
@Min(2) @Max(20)
19-
Integer maxMembers
19+
Integer maxMembers,
20+
21+
@Schema(description = "몇 분동안 진행되는 매칭인지", example = "120")
22+
int durationMinutes,
23+
24+
@Schema(description = "매칭 참여 요금", example = "4000")
25+
@Min(value = 1000, message = "참가비는 1000원 이상이어야 합니다.")
26+
int entryFee
2027

2128
) {}

src/main/java/com/be/sportizebe/domain/match/dto/response/MatchNearResponse.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,10 @@ public record MatchNearResponse(
1212
int curMembers,
1313
int maxMembers,
1414
MatchStatus status,
15-
int distanceM
15+
int distanceM,
16+
int durationMinutes,
17+
int entryFee
18+
1619
) {
1720
public static MatchNearResponse from(MatchNearProjection p) {
1821
return new MatchNearResponse(
@@ -23,7 +26,10 @@ public static MatchNearResponse from(MatchNearProjection p) {
2326
p.getCurMembers(),
2427
p.getMaxMembers(),
2528
MatchStatus.valueOf(p.getStatus()),
26-
(int) Math.round(p.getDistanceM())
29+
(int) Math.round(p.getDistanceM()),
30+
p.getDurationMinutes(),
31+
p.getEntryFee()
32+
2733
);
2834
}
2935
}

src/main/java/com/be/sportizebe/domain/match/entity/MatchParticipant.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,4 +59,10 @@ public void leave() {
5959
public boolean isJoined() {
6060
return this.status == MatchParticipantStatus.JOINED;
6161
}
62+
63+
public void rejoin() {
64+
this.status = MatchParticipantStatus.JOINED;
65+
this.joinedAt = LocalDateTime.now();
66+
this.leftAt = null;
67+
}
6268
}
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.be.sportizebe.domain.match.entity;
22

33
public enum MatchParticipantStatus {
4-
JOINED, LEFT
4+
JOINED,
5+
LEFT
56
}

src/main/java/com/be/sportizebe/domain/match/entity/MatchRoom.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,13 @@ public class MatchRoom extends BaseTimeEntity {
3939
@Column(nullable = false)
4040
private MatchStatus status;
4141

42+
@Column(nullable = false)
43+
private int durationMinutes;
44+
45+
@Column(nullable = false)
46+
private int entryFee;
47+
48+
4249
@OneToMany(mappedBy = "matchRoom", cascade = CascadeType.ALL, orphanRemoval = true)
4350
@Builder.Default
4451
private List<MatchParticipant> participants = new ArrayList<>();
@@ -54,6 +61,18 @@ public static MatchRoom create(MatchCreateRequest request) {
5461
.curMembers(0)
5562
.maxMembers(request.maxMembers())
5663
.status(MatchStatus.OPEN)
64+
.durationMinutes(request.durationMinutes())
65+
.entryFee(request.entryFee())
5766
.build();
5867
}
68+
public void join() {
69+
this.curMembers++;
70+
if (isFull()) this.status = MatchStatus.FULL;
71+
}
72+
public void leave() {
73+
this.curMembers--;
74+
if (this.status == MatchStatus.FULL) this.status = MatchStatus.OPEN;
75+
}
76+
77+
5978
}

src/main/java/com/be/sportizebe/domain/match/exception/MatchErrorCode.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@ public enum MatchErrorCode implements BaseErrorCode {
2323
HttpStatus.BAD_REQUEST,
2424
"MATCH_400_ALREADY_JOINED",
2525
"이미 해당 매칭에 참가 중입니다."
26+
),
27+
28+
NOT_JOINED(
29+
HttpStatus.BAD_REQUEST,
30+
"MATCH_400_NOT_JOINED",
31+
"해당 매칭에 참가 중이지 않습니다."
2632
);
2733

2834
private final HttpStatus status;

src/main/java/com/be/sportizebe/domain/match/repository/MatchParticipantRepository.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import org.springframework.data.jpa.repository.JpaRepository;
88

99
import java.util.List;
10+
import java.util.Optional;
1011

1112
public interface MatchParticipantRepository extends JpaRepository<MatchParticipant, Long> {
1213

@@ -18,4 +19,10 @@ public interface MatchParticipantRepository extends JpaRepository<MatchParticipa
1819

1920
// 주어진 방에 참여중인 참가자 리스트 전체 조회
2021
List<MatchParticipant> findAllByMatchRoomAndStatus(MatchRoom matchRoom, MatchParticipantStatus status);
22+
23+
// 특정 유저의 특정 매칭방 참가 이력 단건 조회 (상태 포함)
24+
Optional<MatchParticipant> findByMatchRoomAndUserAndStatus(MatchRoom matchRoom, User user, MatchParticipantStatus status);
25+
26+
// 특정 유저의 특정 매칭방 참가 이력 단건 조회 (상태 무관)
27+
Optional<MatchParticipant> findByMatchRoomAndUser(MatchRoom matchRoom, User user);
2128
}

src/main/java/com/be/sportizebe/domain/match/repository/MatchRoomRepository.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ public interface MatchRoomRepository extends JpaRepository<MatchRoom, Long> {
1919
mr.cur_members AS curMembers,
2020
mr.max_members AS maxMembers,
2121
mr.status AS status,
22+
mr.duration_minutes AS durationMinutes,
23+
mr.entry_fee AS entryFee,
24+
2225
ST_Distance(
2326
sf.location,
2427
ST_SetSRID(ST_MakePoint(:lng, :lat), 4326)::geography

src/main/java/com/be/sportizebe/domain/match/repository/projection/MatchNearProjection.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,6 @@ public interface MatchNearProjection {
99
Integer getMaxMembers();
1010
String getStatus();
1111
Double getDistanceM();
12+
Integer getDurationMinutes();
13+
Integer getEntryFee();
1214
}

0 commit comments

Comments
 (0)