Skip to content

Commit c85bac5

Browse files
authored
Merge pull request #58 from Sportize/feat/match
Feat/match
2 parents f534071 + 8471a96 commit c85bac5

File tree

13 files changed

+117
-8
lines changed

13 files changed

+117
-8
lines changed

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

Lines changed: 13 additions & 2 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;
@@ -37,7 +38,7 @@ public class MatchController {
3738

3839
private final MatchService matchService;
3940

40-
@Operation(summary = "매칭 생성")
41+
@Operation(summary = "매칭 생성 (관리자 전용 기능)", description = "현재는 매칭 더미데이터 넣는 용도")
4142
@PostMapping
4243
public ResponseEntity<BaseResponse<MatchResponse>> createMatch(
4344
@AuthenticationPrincipal UserAuthInfo userAuthInfo,
@@ -68,7 +69,17 @@ public ResponseEntity<BaseResponse<MatchDetailResponse>> getMatchDetail(
6869
return ResponseEntity.ok(BaseResponse.success("매칭 상세 조회 성공", response));
6970
}
7071

71-
@Operation(summary = "내 주변 매칭 목록 조회")
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+
82+
@Operation(summary = "내 주변 매칭 목록 조회", description = "매칭상태가 OPEN인 매칭들만 보여준다.")
7283
@GetMapping("/near")
7384
public ResponseEntity<BaseResponse<List<MatchNearResponse>>> getNearMatches(
7485
@ParameterObject @Valid @ModelAttribute MatchNearRequest request

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/request/MatchNearRequest.java

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

33
import com.be.sportizebe.common.enums.SportType;
4+
import io.swagger.v3.oas.annotations.media.Schema;
45
import jakarta.validation.constraints.*;
56
import lombok.Getter;
67
import lombok.Setter;
@@ -9,19 +10,23 @@
910
@Setter
1011
public class MatchNearRequest {
1112

13+
@Schema(description = "위도", example = "37.2662", requiredMode = Schema.RequiredMode.REQUIRED)
1214
@NotNull(message = "위도(lat)는 필수입니다")
1315
@DecimalMin(value = "-90.0", message = "위도는 -90.0 이상이어야 합니다")
1416
@DecimalMax(value = "90.0", message = "위도는 90.0 이하여야 합니다")
1517
private Double lat;
1618

19+
@Schema(description = "경도", example = "127.0006", requiredMode = Schema.RequiredMode.REQUIRED)
1720
@NotNull(message = "경도(lng)는 필수입니다")
1821
@DecimalMin(value = "-180.0", message = "경도는 -180.0 이상이어야 합니다")
1922
@DecimalMax(value = "180.0", message = "경도는 180.0 이하여야 합니다")
2023
private Double lng;
2124

25+
@Schema(description = "반경(미터)", example = "1000", defaultValue = "1000")
2226
@Min(value = 100, message = "반경은 최소 100m 이상이어야 합니다")
2327
@Max(value = 10000, message = "반경은 최대 10km까지 가능합니다")
2428
private Integer radiusM = 1000;
2529

30+
@Schema(description = "종목 필터(선택)", example = "BASKETBALL", nullable = true)
2631
private SportType sportsName;
2732
}

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

0 commit comments

Comments
 (0)