Skip to content

Commit 86a8205

Browse files
committed
round1: 리뷰 적용
포인트 1:1로 관계 수정 도메인 분리(User.currentPoint 제거)
1 parent 4faa67e commit 86a8205

11 files changed

Lines changed: 101 additions & 81 deletions

File tree

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,32 @@
11
package com.loopers.application.point;
22

33
import com.loopers.domain.point.PointService;
4+
import com.loopers.domain.user.User;
45
import com.loopers.domain.user.UserService;
56
import com.loopers.support.error.CoreException;
67
import com.loopers.support.error.ErrorType;
78
import lombok.RequiredArgsConstructor;
89
import org.springframework.stereotype.Component;
10+
import org.springframework.transaction.annotation.Transactional;
911

1012
@RequiredArgsConstructor
1113
@Component
1214
public class PointFacade {
13-
private final UserService userService;
1415
private final PointService pointService;
16+
private final UserService userService;
1517

18+
@Transactional(readOnly = true)
1619
public Long getCurrentPoint(String userId) {
17-
return userService.getCurrentPoint(userId)
20+
User user = userService.findByUserId(userId).orElseThrow(() -> new CoreException(ErrorType.NOT_FOUND, "사용자를 찾을 수 없습니다."));
21+
22+
return pointService.getCurrentPoint(user.getId())
1823
.orElseThrow(() -> new CoreException(ErrorType.NOT_FOUND, "사용자를 찾을 수 없습니다."));
1924
}
2025

21-
public Long chargePoints(String userId, int amount) {
22-
return pointService.chargePoint(userId, amount);
26+
@Transactional
27+
public Long chargePoint(String userId, int amount) {
28+
User user = userService.findByUserIdForUpdate(userId).orElseThrow(() -> new CoreException(ErrorType.NOT_FOUND, "사용자를 찾을 수 없습니다."));
29+
30+
return pointService.chargePoint(user.getId(), amount);
2331
}
2432
}

apps/commerce-api/src/main/java/com/loopers/application/user/UserFacade.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,26 @@
11
package com.loopers.application.user;
22

3+
import com.loopers.domain.point.PointService;
34
import com.loopers.domain.user.User;
45
import com.loopers.domain.user.UserService;
56
import com.loopers.support.error.CoreException;
67
import com.loopers.support.error.ErrorType;
78
import lombok.RequiredArgsConstructor;
89
import org.springframework.stereotype.Component;
10+
import org.springframework.transaction.annotation.Transactional;
911

1012
import java.util.Optional;
1113

1214
@RequiredArgsConstructor
1315
@Component
1416
public class UserFacade {
1517
private final UserService userService;
18+
private final PointService pointService;
1619

20+
@Transactional
1721
public UserInfo registerUser(String userId, String email, String birthday, String gender) {
1822
User registeredUser = userService.registerUser(userId, email, birthday, gender);
23+
pointService.createPoint(registeredUser.getId());
1924
return UserInfo.from(registeredUser);
2025
}
2126

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,38 @@
11
package com.loopers.domain.point;
22

33
import com.loopers.domain.BaseEntity;
4-
import com.loopers.domain.user.User;
54
import com.loopers.support.error.CoreException;
65
import com.loopers.support.error.ErrorType;
6+
import jakarta.persistence.Column;
77
import jakarta.persistence.Entity;
8-
import jakarta.persistence.JoinColumn;
9-
import jakarta.persistence.ManyToOne;
108
import jakarta.persistence.Table;
119
import lombok.Getter;
1210

1311
@Entity
1412
@Table(name = "point")
1513
@Getter
1614
public class Point extends BaseEntity {
17-
@ManyToOne
18-
@JoinColumn(referencedColumnName = "id", nullable = false, updatable = false)
19-
private User user;
15+
@Column(name = "user_id", nullable = false, updatable = false, unique = true)
16+
private Long userId;
2017
private Long amount;
2118

2219
protected Point() {
2320
}
2421

25-
private Point(User user, Long amount) {
26-
this.user = user;
22+
private Point(Long userId, Long amount) {
23+
this.userId = userId;
2724
this.amount = amount;
2825
}
2926

30-
public static Point create(User user, int amount) {
27+
public static Point create(Long userId) {
28+
return new Point(userId, 0L);
29+
}
30+
31+
public void charge(int amount) {
3132
if (amount <= 0) {
3233
throw new CoreException(ErrorType.BAD_REQUEST, "충전 포인트는 0보다 커야 합니다.");
3334
}
3435

35-
return new Point(user, (long) amount);
36+
this.amount += amount;
3637
}
3738
}

apps/commerce-api/src/main/java/com/loopers/domain/point/PointJpaRepository.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@
33
import org.springframework.data.jpa.repository.JpaRepository;
44
import org.springframework.stereotype.Repository;
55

6+
import java.util.Optional;
7+
68
@Repository
79
public interface PointJpaRepository extends JpaRepository<Point, Long> {
810

11+
Optional<Point> findByUserId(Long userId);
912
}
Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,35 @@
11
package com.loopers.domain.point;
22

3-
import com.loopers.domain.user.User;
4-
import com.loopers.domain.user.UserService;
53
import com.loopers.support.error.CoreException;
64
import com.loopers.support.error.ErrorType;
75
import lombok.RequiredArgsConstructor;
86
import org.springframework.stereotype.Service;
97
import org.springframework.transaction.annotation.Transactional;
108

9+
import java.util.Optional;
10+
1111
@RequiredArgsConstructor
1212
@Service
1313
public class PointService {
1414
private final PointJpaRepository pointJpaRepository;
15-
private final UserService userService;
1615

1716
@Transactional
18-
public Long chargePoint(String userId, int amount) {
19-
User user = userService.findByUserIdForUpdate(userId).orElseThrow(() -> new CoreException(ErrorType.NOT_FOUND, "사용자를 찾을 수 없습니다."));
20-
21-
Point point = Point.create(user, amount);
17+
public void createPoint(Long userId) {
18+
Point point = Point.create(userId);
19+
pointJpaRepository.save(point);
20+
}
2221

23-
user.setCurrentPoint(user.getCurrentPoint() + amount);
22+
@Transactional
23+
public Long chargePoint(Long userId, int amount) {
24+
Point point = pointJpaRepository.findByUserId(userId)
25+
.orElseThrow(() -> new CoreException(ErrorType.NOT_FOUND, "포인트 정보를 찾을 수 없습니다."));
26+
point.charge(amount);
2427
pointJpaRepository.save(point);
28+
return point.getAmount();
29+
}
2530

26-
return user.getCurrentPoint();
31+
@Transactional(readOnly = true)
32+
public Optional<Long> getCurrentPoint(Long userId) {
33+
return pointJpaRepository.findByUserId(userId).map(Point::getAmount);
2734
}
2835
}

apps/commerce-api/src/main/java/com/loopers/domain/user/User.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
import jakarta.persistence.Entity;
88
import jakarta.persistence.Table;
99
import lombok.Getter;
10-
import lombok.Setter;
1110
import org.apache.commons.lang3.StringUtils;
1211

1312
@Entity
@@ -22,8 +21,6 @@ protected User() {
2221
private String email;
2322
private String birthday;
2423
private String gender;
25-
@Setter
26-
private Long currentPoint = 0L;
2724

2825
private User(String userId, String email, String birthday, String gender) {
2926
this.userId = userId;

apps/commerce-api/src/main/java/com/loopers/domain/user/UserService.java

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,5 @@ public Optional<User> findByUserId(String userId) {
3333
public Optional<User> findByUserIdForUpdate(String userId) {
3434
return userJpaRepository.findByUserIdForUpdate(userId);
3535
}
36-
@Transactional(readOnly = true)
37-
public Optional<Long> getCurrentPoint(String userId) {
38-
return findByUserId(userId).map(User::getCurrentPoint);
39-
}
36+
4037
}

apps/commerce-api/src/main/java/com/loopers/interfaces/api/point/PointV1Controller.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ public ApiResponse<PointV1Dto.PointResponse> chargeUserPoints(
3434
if (StringUtils.isBlank(userId)) {
3535
throw new CoreException(ErrorType.BAD_REQUEST);
3636
}
37-
Long chargedPoint = pointFacade.chargePoints(userId, request.amount());
37+
Long chargedPoint = pointFacade.chargePoint(userId, request.amount());
3838
PointV1Dto.PointResponse response = PointV1Dto.PointResponse.from(chargedPoint);
3939
return ApiResponse.success(response);
4040
}

apps/commerce-api/src/test/java/com/loopers/domain/point/PointModelTest.java

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package com.loopers.domain.point;
22

3-
import com.loopers.domain.user.User;
43
import com.loopers.support.error.CoreException;
54
import org.junit.jupiter.api.DisplayName;
65
import org.junit.jupiter.api.Nested;
@@ -20,15 +19,9 @@ class Create {
2019
@ValueSource(ints = {0, -10, -100})
2120
void throwsException_whenPointIsZeroOrNegative(int invalidPoint) {
2221
// arrange
23-
String validId = "user123";
24-
String validEmail = "xx@yy.zz";
25-
String validBirthday = "1993-03-13";
26-
String validGender = "male";
27-
28-
User user = User.create(validId, validEmail, validBirthday, validGender);
29-
22+
Point point = Point.create(0L);
3023
// act
31-
CoreException result = assertThrows(CoreException.class, () -> Point.create(user, invalidPoint));
24+
CoreException result = assertThrows(CoreException.class, () -> point.charge(invalidPoint));
3225

3326
// assert
3427
assertThat(result.getMessage()).isEqualTo("충전 포인트는 0보다 커야 합니다.");

apps/commerce-api/src/test/java/com/loopers/domain/point/PointServiceIntegrationTest.java

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,68 @@
11
package com.loopers.domain.point;
22

3+
import com.loopers.application.point.PointFacade;
4+
import com.loopers.domain.user.User;
5+
import com.loopers.domain.user.UserService;
36
import com.loopers.support.error.CoreException;
7+
import org.junit.jupiter.api.BeforeEach;
48
import org.junit.jupiter.api.DisplayName;
59
import org.junit.jupiter.api.Test;
610
import org.springframework.beans.factory.annotation.Autowired;
711
import org.springframework.boot.test.context.SpringBootTest;
812
import org.springframework.transaction.annotation.Transactional;
913

14+
import java.util.Optional;
15+
16+
import static org.assertj.core.api.Assertions.assertThat;
1017
import static org.junit.jupiter.api.Assertions.assertThrows;
1118

1219
@SpringBootTest
1320
@Transactional
1421
public class PointServiceIntegrationTest {
22+
@Autowired
23+
private PointFacade pointFacade;
1524
@Autowired
1625
private PointService pointService;
26+
@Autowired
27+
private UserService userService;
28+
29+
@BeforeEach
30+
void setUp() {
31+
String validId = "user123";
32+
String validEmail = "xx@yy.zz";
33+
String validBirthday = "1993-03-13";
34+
String validGender = "male";
35+
// 유저 등록
36+
User registeredUser = userService.registerUser(validId, validEmail, validBirthday, validGender);
37+
pointService.createPoint(registeredUser.getId());
38+
}
39+
40+
@DisplayName("해당 ID 의 회원이 존재할 경우, 보유 포인트가 반환된다.")
41+
@Test
42+
void returnsUserPoints_whenUserExists() {
43+
// arrange: setUp() 메서드에서 이미 유저 등록
44+
String existingUserId = "user123";
45+
Long userId = userService.findByUserId(existingUserId).get().getId();
46+
47+
// act
48+
Optional<Long> currentPoint = pointService.getCurrentPoint(userId);
49+
50+
// assert
51+
assertThat(currentPoint.orElse(null)).isEqualTo(0L);
52+
}
53+
54+
@DisplayName("해당 ID 의 회원이 존재하지 않을 경우, null 이 반환된다.")
55+
@Test
56+
void returnsNullPoints_whenUserDoesNotExist() {
57+
// arrange: setUp() 메서드에서 등록되지 않은 유저 ID 사용
58+
Long nonExistingUserId = -1L;
59+
60+
// act
61+
Optional<Long> currentPoint = pointService.getCurrentPoint(nonExistingUserId);
62+
63+
// assert
64+
assertThat(currentPoint).isNotPresent();
65+
}
1766

1867
//존재하지 않는 유저 ID 로 충전을 시도한 경우, 실패한다.
1968
@DisplayName("존재하지 않는 유저 ID 로 충전을 시도한 경우, 실패한다.")
@@ -24,7 +73,6 @@ void throwsExceptionWhenChargePointWithNonExistingUserId() {
2473
int chargeAmount = 1000;
2574

2675
// act & assert
27-
assertThrows(CoreException.class, () -> pointService.chargePoint(nonExistingUserId, chargeAmount));
76+
assertThrows(CoreException.class, () -> pointFacade.chargePoint(nonExistingUserId, chargeAmount));
2877
}
29-
3078
}

0 commit comments

Comments
 (0)