Skip to content

Commit baac2d5

Browse files
committed
feat: GET /api/v1/friends/requests/sent - 내가 보낸 친구 요청 목록 API 추가
- FriendRepository: findPendingRequestsByRequesterId() 추가 - FriendReader: findSentRequests() - requesterId 기준 PENDING 목록 조회 - FriendService: findSentRequests() delegate 추가 - FriendController: GET /requests/sent 엔드포인트 추가 - FriendControllerTest: findSentRequests 테스트 추가 - friend-api.adoc: Find Sent Friend Requests 섹션 추가
1 parent ae515b9 commit baac2d5

8 files changed

Lines changed: 91 additions & 3 deletions

File tree

api/src/docs/asciidoc/friend-api.adoc

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,16 @@ include::{snippets}/findPendingFriendRequests/response-fields.adoc[]
3434

3535
'''
3636

37+
=== Find Sent Friend Requests
38+
==== HTTP Request
39+
include::{snippets}/findSentFriendRequests/http-request.adoc[]
40+
==== HTTP Response
41+
include::{snippets}/findSentFriendRequests/http-response.adoc[]
42+
==== Response Fields
43+
include::{snippets}/findSentFriendRequests/response-fields.adoc[]
44+
45+
'''
46+
3747
=== Accept Friend Request
3848
==== HTTP Request
3949
include::{snippets}/acceptFriendRequest/http-request.adoc[]

api/src/main/kotlin/com/benecia/lifetracker/domain/friend/api/FriendController.kt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,15 @@ class FriendController(
4646
return ApiResponse.success(responseList)
4747
}
4848

49+
@GetMapping("/requests/sent")
50+
fun findSentRequests(
51+
@AuthenticationPrincipal loginUser: LoginUser,
52+
): ApiResponse<List<FriendResponse>> {
53+
val requests = friendService.findSentRequests(loginUser.id)
54+
val responseList = requests.map { FriendResponse.of(it) }
55+
return ApiResponse.success(responseList)
56+
}
57+
4958
@PostMapping("/{friendRequestId}/accept")
5059
fun acceptRequest(
5160
@AuthenticationPrincipal loginUser: LoginUser,

api/src/test/kotlin/com/benecia/lifetracker/domain/friend/api/FriendControllerTest.kt

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,48 @@ class FriendControllerTest : RestDocsTest() {
167167
)
168168
}
169169

170+
@Test
171+
fun findSentRequests() {
172+
val userId = UUID.randomUUID()
173+
val loginUser = createLoginUser(userId)
174+
175+
setupAuthentication(loginUser)
176+
177+
val sentList = listOf(
178+
FriendInfo(
179+
id = 3L,
180+
friendId = UUID.randomUUID(),
181+
friendProvider = "naver",
182+
friendDisplayName = "수신자1",
183+
friendProfileImageUrl = "https://img.com/3.png",
184+
),
185+
)
186+
every { friendService.findSentRequests(userId) } returns sentList
187+
188+
given()
189+
.contentType(ContentType.JSON)
190+
.get("/api/v1/friends/requests/sent")
191+
.then()
192+
.status(HttpStatus.OK)
193+
.apply(
194+
document(
195+
"findSentFriendRequests",
196+
requestPreprocessor(),
197+
responsePreprocessor(),
198+
responseFields(
199+
fieldWithPath("status").type(JsonFieldType.NUMBER).description("HTTP 상태 코드"),
200+
fieldWithPath("message").type(JsonFieldType.STRING).description("응답 메시지"),
201+
fieldWithPath("data[].id").type(JsonFieldType.NUMBER).description("친구 요청 ID"),
202+
fieldWithPath("data[].friendId").type(JsonFieldType.STRING).description("수신자 UUID"),
203+
fieldWithPath("data[].friendProvider").type(JsonFieldType.STRING).description("수신자의 OAuth 프로바이더"),
204+
fieldWithPath("data[].friendDisplayName").type(JsonFieldType.STRING).description("수신자 이름"),
205+
fieldWithPath("data[].friendProfileImageUrl").type(JsonFieldType.STRING).description("수신자 프로필 이미지 URL").optional(),
206+
fieldWithPath("timestamp").type(JsonFieldType.STRING).description("응답 생성 시간"),
207+
),
208+
),
209+
)
210+
}
211+
170212
@Test
171213
fun acceptRequest() {
172214
val userId = UUID.randomUUID()

core/user-core/src/main/kotlin/com/benecia/lifetracker/user/service/FriendReader.kt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,19 @@ class FriendReader(
3939
)
4040
}
4141
}
42+
43+
fun findSentRequests(userId: UUID): List<FriendInfo> {
44+
val friends = friendRepository.findPendingRequestsByRequesterId(userId)
45+
46+
return friends.map {
47+
val receiver = userReader.findById(it.receiverId)
48+
FriendInfo(
49+
id = it.id!!,
50+
friendId = receiver.id,
51+
friendProvider = receiver.provider,
52+
friendDisplayName = receiver.displayName,
53+
friendProfileImageUrl = receiver.profileImageUrl,
54+
)
55+
}
56+
}
4257
}

core/user-core/src/main/kotlin/com/benecia/lifetracker/user/service/FriendRepository.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ interface FriendRepository {
99
fun exists(requesterId: UUID, receiverId: UUID): Boolean
1010
fun findAllByUserId(userId: UUID): List<Friend>
1111
fun findPendingRequestsByReceiverId(receiverId: UUID): List<Friend>
12+
fun findPendingRequestsByRequesterId(requesterId: UUID): List<Friend>
1213
fun findFriendRequestById(friendRequestId: Long): Friend
1314
fun changeFriendRequestStatus(friendRequestId: Long, status: FriendStatus): Long
1415
fun delete(userId: UUID, friendId: Long)

core/user-core/src/main/kotlin/com/benecia/lifetracker/user/service/FriendService.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ class FriendService(
2222
return friendReader.findPendingRequests(userId)
2323
}
2424

25+
fun findSentRequests(userId: UUID): List<FriendInfo> {
26+
return friendReader.findSentRequests(userId)
27+
}
28+
2529
fun acceptRequest(userId: UUID, friendRequestId: Long): Long {
2630
return friendAppender.acceptRequest(userId, friendRequestId)
2731
}

storage/db-core-jpa/src/main/kotlin/com/benecia/lifetracker/db/jpa/user/FriendEntityRepository.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,11 @@ class FriendEntityRepository(
3636
.map { it.toDomain() }
3737
}
3838

39+
override fun findPendingRequestsByRequesterId(requesterId: UUID): List<Friend> {
40+
return friendJpaRepository.findAllByRequesterIdAndStatus(requesterId, FriendStatus.PENDING)
41+
.map { it.toDomain() }
42+
}
43+
3944
override fun findFriendRequestById(friendRequestId: Long): Friend {
4045
return friendJpaRepository.findByIdOrNull(friendRequestId)
4146
?.toDomain()

storage/db-core-jpa/src/main/kotlin/com/benecia/lifetracker/db/jpa/user/FriendJpaRepository.kt

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,12 @@ import com.benecia.lifetracker.user.service.FriendStatus
44
import org.springframework.data.jpa.repository.JpaRepository
55
import java.util.UUID
66

7-
interface FriendJpaRepository : JpaRepository<com.benecia.lifetracker.db.jpa.user.FriendEntity, Long> {
7+
interface FriendJpaRepository : JpaRepository<FriendEntity, Long> {
88
fun existsByRequesterIdAndReceiverId(requesterId: UUID, receiverId: UUID): Boolean
99

10-
fun findAllByRequesterIdOrReceiverId(requesterId: UUID, receiverId: UUID): List<com.benecia.lifetracker.db.jpa.user.FriendEntity>
10+
fun findAllByRequesterIdOrReceiverId(requesterId: UUID, receiverId: UUID): List<FriendEntity>
1111

12-
fun findAllByReceiverIdAndStatus(receiverId: UUID, status: FriendStatus): List<com.benecia.lifetracker.db.jpa.user.FriendEntity>
12+
fun findAllByReceiverIdAndStatus(receiverId: UUID, status: FriendStatus): List<FriendEntity>
13+
14+
fun findAllByRequesterIdAndStatus(requesterId: UUID, status: FriendStatus): List<FriendEntity>
1315
}

0 commit comments

Comments
 (0)