Skip to content

Commit 243dbaf

Browse files
authored
Merge pull request #23 from moddo-kr/feature/get-settlement
feat: 정산 리스트 조회시 총 정산 금액 응답에 포함하도록 수정
2 parents fa5a798 + 1fb08fd commit 243dbaf

14 files changed

Lines changed: 121 additions & 36 deletions

File tree

src/docs/asciidoc/auth.adoc

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -103,31 +103,31 @@ include::{snippets}/auth-controller-test/kakao-logout/response-body.adoc[]
103103

104104
== 토큰 상태 확인
105105

106-
쿠키에 담긴 토큰의 유효성을 확인합니다
106+
쿠키에 담긴 토큰의 유효성을 확인합니다.
107107

108108
=== Example
109109

110-
include::{snippets}/auth-controller-test/check-auth_-success/http-request.adoc[]
110+
include::{snippets}/auth-controller-test/check-auth-success/http-request.adoc[]
111111

112112
=== HTTP
113113

114114
==== 요청
115115

116-
include::{snippets}/auth-controller-test/check-auth_-success/curl-request.adoc[]
116+
include::{snippets}/auth-controller-test/check-auth-success/curl-request.adoc[]
117117

118118
==== 응답
119119

120-
include::{snippets}/auth-controller-test/check-auth_-success/http-response.adoc[]
120+
include::{snippets}/auth-controller-test/check-auth-success/http-response.adoc[]
121121

122122
=== Body
123123

124124
==== 응답 (valid)
125125

126-
include::{snippets}/auth-controller-test/check-auth_-success/response-body.adoc[]
126+
include::{snippets}/auth-controller-test/check-auth-success/response-body.adoc[]
127127

128128
==== 응답 (invalid)
129129

130-
include::{snippets}/auth-controller-test/check-auth_-expired/response-body.adoc[]
130+
include::{snippets}/auth-controller-test/check-auth-expired/response-body.adoc[]
131131

132-
include::{snippets}/auth-controller-test/check-auth_-invalid-token/response-body.adoc[]
132+
include::{snippets}/auth-controller-test/check-auth-invalid-token/response-body.adoc[]
133133

src/docs/asciidoc/settlement.adoc

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -146,20 +146,20 @@ user가 속한 정산의 공유 링크 리스트를 조회할 수 있다.
146146

147147
=== Example
148148

149-
include::{snippets}/settlement-controller-test/get-share-link-list_-success/curl-request.adoc[]
149+
include::{snippets}/settlement-controller-test/get-share-link-list-success/curl-request.adoc[]
150150

151151
=== HTTP
152152

153153
==== 요청
154154

155-
include::{snippets}/settlement-controller-test/get-share-link-list_-success/http-request.adoc[]
155+
include::{snippets}/settlement-controller-test/get-share-link-list-success/http-request.adoc[]
156156

157157
==== 응답
158158

159-
include::{snippets}/settlement-controller-test/get-share-link-list_-success/http-response.adoc[]
159+
include::{snippets}/settlement-controller-test/get-share-link-list-success/http-response.adoc[]
160160

161161
=== Body
162162

163163
==== 응답
164164

165-
include::{snippets}/settlement-controller-test/get-share-link-list_-success/response-body.adoc[]
165+
include::{snippets}/settlement-controller-test/get-share-link-list-success/response-body.adoc[]

src/main/java/com/dnd/moddo/auth/presentation/AuthController.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package com.dnd.moddo.auth.presentation;
22

3+
import static com.dnd.moddo.auth.infrastructure.security.JwtConstants.*;
4+
35
import java.io.IOException;
46
import java.util.Collections;
57

@@ -100,8 +102,8 @@ public ResponseEntity<AuthCheckResponse> checkAuth(
100102
try {
101103
Claims claims = jwtProvider.parseClaims(token);
102104

103-
Long userId = jwtProvider.getUserId(token);
104-
String role = jwtProvider.getRole(token);
105+
Long userId = claims.get(AUTH_ID.getMessage(), Long.class);
106+
String role = claims.get(ROLE.getMessage(), String.class);
105107

106108
return ResponseEntity.ok(
107109
AuthCheckResponse.success(userId, role)

src/main/java/com/dnd/moddo/auth/presentation/response/AuthCheckResponse.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
package com.dnd.moddo.auth.presentation.response;
22

3+
import com.fasterxml.jackson.annotation.JsonInclude;
4+
5+
@JsonInclude(JsonInclude.Include.NON_NULL)
36
public record AuthCheckResponse(
47
boolean authenticated,
58
UserInfo user,

src/main/java/com/dnd/moddo/common/exception/GlobalExceptionHandler.java

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -70,12 +70,9 @@ public ResponseEntity<ErrorResponse> handleValidation(
7070
MethodArgumentNotValidException e
7171
) {
7272

73-
String message = e.getBindingResult()
74-
.getFieldErrors()
75-
.stream()
76-
.findFirst()
77-
.map(error -> error.getField() + " : " + error.getDefaultMessage())
78-
.orElse("잘못된 요청입니다.");
73+
LoggingUtils.warn(e);
74+
75+
String message = e.getMessage();
7976

8077
return ResponseEntity.badRequest()
8178
.body(new ErrorResponse(400, message));

src/main/java/com/dnd/moddo/event/application/query/QuerySettlementService.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import com.dnd.moddo.event.application.impl.SettlementValidator;
1010
import com.dnd.moddo.event.domain.member.Member;
1111
import com.dnd.moddo.event.domain.settlement.Settlement;
12+
import com.dnd.moddo.event.domain.settlement.type.SettlementSortType;
1213
import com.dnd.moddo.event.domain.settlement.type.SettlementStatus;
1314
import com.dnd.moddo.event.presentation.request.SearchSettlementListRequest;
1415
import com.dnd.moddo.event.presentation.response.SettlementDetailResponse;
@@ -51,9 +52,12 @@ public List<SettlementListResponse> search(
5152
SettlementStatus effectiveStatus =
5253
request.status() == null ? SettlementStatus.ALL : request.status();
5354

55+
SettlementSortType effectiveSort =
56+
request.sort() == null ? SettlementSortType.LATEST : request.sort();
57+
5458
int limit = request.limit() == null ? 10 : request.limit();
5559

56-
return settlementReader.findListByUserIdAndStatus(userId, effectiveStatus, request.sort(), limit);
60+
return settlementReader.findListByUserIdAndStatus(userId, effectiveStatus, effectiveSort, limit);
5761
}
5862

5963
public List<SettlementShareResponse> findSettlementShareList(Long userId) {

src/main/java/com/dnd/moddo/event/infrastructure/SettlementQueryRepositoryImpl.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import org.springframework.stereotype.Repository;
66

7+
import com.dnd.moddo.event.domain.expense.QExpense;
78
import com.dnd.moddo.event.domain.member.QMember;
89
import com.dnd.moddo.event.domain.settlement.QSettlement;
910
import com.dnd.moddo.event.domain.settlement.type.SettlementSortType;
@@ -15,6 +16,8 @@
1516
import com.querydsl.core.types.dsl.BooleanExpression;
1617
import com.querydsl.core.types.dsl.Expressions;
1718
import com.querydsl.core.types.dsl.NumberExpression;
19+
import com.querydsl.jpa.JPAExpressions;
20+
import com.querydsl.jpa.JPQLQuery;
1821
import com.querydsl.jpa.impl.JPAQueryFactory;
1922

2023
import lombok.RequiredArgsConstructor;
@@ -35,6 +38,7 @@ public List<SettlementListResponse> findByUserAndStatus(
3538
) {
3639
QSettlement settlement = QSettlement.settlement;
3740
QMember member = QMember.member;
41+
QExpense expense = QExpense.expense;
3842

3943
BooleanExpression userCondition =
4044
member.user.id.eq(userId);
@@ -61,6 +65,12 @@ public List<SettlementListResponse> findByUserAndStatus(
6165
member.isPaid
6266
);
6367

68+
JPQLQuery<Long> totalAmount =
69+
JPAExpressions
70+
.select(expense.amount.sum().coalesce(0L))
71+
.from(expense)
72+
.where(expense.settlement.id.eq(settlement.id));
73+
6474
OrderSpecifier<?> orderSpecifier =
6575
getOrderSpecifier(sortType, settlement, memberCount, completedCount);
6676

@@ -70,6 +80,7 @@ public List<SettlementListResponse> findByUserAndStatus(
7080
settlement.id,
7181
settlement.code,
7282
settlement.name,
83+
totalAmount,
7384
memberCount,
7485
completedCount.coalesce(0L),
7586
settlement.createdAt,

src/main/java/com/dnd/moddo/event/presentation/request/SearchSettlementListRequest.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ public record SearchSettlementListRequest(
1515
@NotNull(message = "정렬 방식은 필수입니다.")
1616
SettlementSortType sort,
1717

18+
@NotNull(message = "limit은 필수입니다.")
1819
@Min(value = 1, message = "limit은 1 이상이어야 합니다.")
1920
@Max(value = 100, message = "limit은 최대 100까지 가능합니다.")
2021
Integer limit

src/main/java/com/dnd/moddo/event/presentation/response/SettlementListResponse.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ public record SettlementListResponse(
66
Long groupId,
77
String groupCode,
88
String name,
9+
Long totalAmount,
910
Long totalMemberCount,
1011
Long completedMemberCount,
1112
LocalDateTime createdAt,

src/test/java/com/dnd/moddo/domain/Member/entity/MemberTest.java

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.dnd.moddo.domain.Member.entity;
22

33
import static org.assertj.core.api.Assertions.*;
4+
import static org.mockito.Mockito.*;
45

56
import org.junit.jupiter.api.BeforeEach;
67
import org.junit.jupiter.api.DisplayName;
@@ -10,6 +11,7 @@
1011
import com.dnd.moddo.event.domain.member.Member;
1112
import com.dnd.moddo.event.domain.settlement.Settlement;
1213
import com.dnd.moddo.global.support.GroupTestFactory;
14+
import com.dnd.moddo.user.domain.User;
1315

1416
class MemberTest {
1517

@@ -74,4 +76,65 @@ void testUpdatePaymentStatus() {
7476
assertThat(member.isPaid()).isTrue();
7577
assertThat(member.getPaidAt()).isNotNull();
7678
}
79+
80+
@DisplayName("사용자를 정상적으로 할당할 수 있다.")
81+
@Test
82+
void assignUser_success() {
83+
// given
84+
Member member = Member.builder()
85+
.name("기존이름")
86+
.settlement(mockSettlement)
87+
.role(ExpenseRole.PARTICIPANT)
88+
.isPaid(false)
89+
.build();
90+
91+
User user = mock(User.class);
92+
when(user.getName()).thenReturn("새이름");
93+
94+
// when
95+
member.assignUser(user);
96+
97+
// then
98+
assertThat(member.getUser()).isEqualTo(user);
99+
assertThat(member.getName()).isEqualTo("새이름"); // 동기화 확인
100+
}
101+
102+
@DisplayName("이미 사용자가 연결되어 있으면 예외가 발생한다.")
103+
@Test
104+
void assignUser_throwException_whenUserAlreadyAssigned() {
105+
// given
106+
Member member = Member.builder()
107+
.name("기존이름")
108+
.settlement(mockSettlement)
109+
.role(ExpenseRole.PARTICIPANT)
110+
.isPaid(false)
111+
.build();
112+
113+
User firstUser = mock(User.class);
114+
User secondUser = mock(User.class);
115+
116+
when(firstUser.getName()).thenReturn("첫번째");
117+
when(secondUser.getName()).thenReturn("두번째");
118+
119+
member.assignUser(firstUser);
120+
121+
// when & then
122+
assertThatThrownBy(() -> member.assignUser(secondUser))
123+
.isInstanceOf(IllegalStateException.class)
124+
.hasMessageContaining("이미 사용자와 연결된 멤버입니다.");
125+
}
126+
127+
@DisplayName("null 사용자를 할당하면 예외가 발생한다.")
128+
@Test
129+
void assignUser_throwException_whenUserIsNull() {
130+
Member member = Member.builder()
131+
.name("기존이름")
132+
.settlement(mockSettlement)
133+
.role(ExpenseRole.PARTICIPANT)
134+
.isPaid(false)
135+
.build();
136+
137+
assertThatThrownBy(() -> member.assignUser(null))
138+
.isInstanceOf(NullPointerException.class);
139+
}
77140
}

0 commit comments

Comments
 (0)