Skip to content

Commit 6949a1e

Browse files
authored
Merge pull request #38 from Kimjipang/main
[volume-1] 회원가입, 내 정보 조회, 포인트 충전, 포인트 조회 API 구현 및 테스트 코드 작성
2 parents d5ec397 + 0540076 commit 6949a1e

29 files changed

Lines changed: 1155 additions & 0 deletions
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package com.loopers.application.point;
2+
3+
import com.loopers.domain.point.Point;
4+
import com.loopers.domain.point.PointService;
5+
import com.loopers.domain.user.UserService;
6+
import com.loopers.interfaces.api.point.PointV1Dto;
7+
import lombok.RequiredArgsConstructor;
8+
import org.springframework.stereotype.Component;
9+
import org.springframework.transaction.annotation.Transactional;
10+
11+
@Component
12+
@RequiredArgsConstructor
13+
public class PointFacade {
14+
private final PointService pointService;
15+
private final UserService userService;
16+
17+
@Transactional(readOnly = true)
18+
public PointInfo getPoint(Long userId) {
19+
/*
20+
- [ ] 사용자 존재 여부 확인
21+
- [ ] 포인트 잔액 조회
22+
*/
23+
userService.checkUserExists(userId);
24+
25+
Point point = pointService.getPointBalanceByUserId(userId);
26+
27+
return PointInfo.from(point);
28+
29+
}
30+
31+
@Transactional
32+
public PointInfo chargePoint(PointV1Dto.PointChargeRequest request) {
33+
/*
34+
- [ ] 사용자 존재 여부 확인
35+
- [ ] 충전 금액 유효성 검사
36+
- [ ] 포인트 충전 로직
37+
*/
38+
userService.checkUserExists(request.userId()); // 사용자 존재 여부 확인
39+
40+
Point current = pointService.getPointBalanceByUserId(request.userId());
41+
current.charge(request.amount()); // 포인트 충전 로직
42+
43+
return PointInfo.from(current);
44+
}
45+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package com.loopers.application.point;
2+
3+
import com.loopers.domain.point.Point;
4+
5+
public record PointInfo(Long userId, Long balance) {
6+
public static PointInfo from(Point point) {
7+
return new PointInfo(
8+
point.getUserId(),
9+
point.getBalance()
10+
);
11+
}
12+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package com.loopers.application.user;
2+
3+
import com.loopers.domain.user.UserEntity;
4+
import com.loopers.domain.user.UserService;
5+
import com.loopers.interfaces.api.user.UserV1Dto;
6+
import com.loopers.support.error.CoreException;
7+
import com.loopers.support.error.ErrorType;
8+
import lombok.RequiredArgsConstructor;
9+
import org.springframework.stereotype.Component;
10+
import org.springframework.transaction.annotation.Transactional;
11+
12+
@Component
13+
@RequiredArgsConstructor
14+
public class UserFacade {
15+
16+
private final UserService userService;
17+
18+
@Transactional
19+
public UserInfo signUp(UserV1Dto.SignUpRequest request) {
20+
boolean isExist = userService.existsByLoginId(request.loginId());
21+
22+
if (isExist) {
23+
throw new CoreException(ErrorType.BAD_REQUEST, "이미 존재하는 유저입니다.");
24+
}
25+
26+
UserEntity savedUser = userService.save(request.toEntity());
27+
return UserInfo.from(savedUser);
28+
}
29+
30+
@Transactional(readOnly = true)
31+
public UserInfo getUserByLoginId(String loginId) {
32+
boolean isExist = userService.existsByLoginId(loginId);
33+
34+
if (!isExist) {
35+
throw new CoreException(ErrorType.NOT_FOUND, "해당 유저ID의 사용자가 존재하지 않습니다.");
36+
}
37+
38+
UserEntity userEntity = userService.getUserByLoginId(loginId);
39+
return UserInfo.from(userEntity);
40+
}
41+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package com.loopers.application.user;
2+
3+
import com.loopers.domain.user.Gender;
4+
import com.loopers.domain.user.UserEntity;
5+
6+
public record UserInfo(Long id, String loginId, Gender gender, String email, String birth) {
7+
public static UserInfo from(UserEntity userEntity) {
8+
return new UserInfo(
9+
userEntity.getId(),
10+
userEntity.getLoginId(),
11+
userEntity.getGender(),
12+
userEntity.getEmail(),
13+
userEntity.getBirth()
14+
);
15+
}
16+
17+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package com.loopers.domain.point;
2+
3+
import com.loopers.domain.BaseEntity;
4+
import jakarta.persistence.Column;
5+
import jakarta.persistence.Entity;
6+
import jakarta.persistence.Table;
7+
import lombok.Getter;
8+
import lombok.NoArgsConstructor;
9+
10+
@Getter
11+
@Entity
12+
@Table(name = "point")
13+
@NoArgsConstructor(access = lombok.AccessLevel.PROTECTED)
14+
public class Point extends BaseEntity {
15+
@Column(name = "user_id", nullable = false)
16+
private Long userId;
17+
@Column(nullable = false)
18+
private Long balance;
19+
20+
public Point(Long userId, Long balance) {
21+
PointValidator.validateBalance(balance);
22+
23+
this.userId = userId;
24+
this.balance = balance;
25+
}
26+
27+
public void charge(Long amount) {
28+
PointValidator.validateChargeAmount(amount); // 충전 금액 유효성 검사 (0보다 커야 함)
29+
this.balance += amount;
30+
}
31+
32+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package com.loopers.domain.point;
2+
3+
import java.util.Optional;
4+
5+
public interface PointRepository {
6+
7+
Optional<Point> findByUserId(Long userId);
8+
Point save(Point point);
9+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package com.loopers.domain.point;
2+
3+
import com.loopers.support.error.CoreException;
4+
import com.loopers.support.error.ErrorType;
5+
import lombok.RequiredArgsConstructor;
6+
import org.springframework.stereotype.Component;
7+
8+
@Component
9+
@RequiredArgsConstructor
10+
public class PointService {
11+
private final PointRepository pointRepository;
12+
13+
public Point getPointBalanceByUserId(Long userId) {
14+
return pointRepository.findByUserId(userId).orElseThrow(
15+
() -> new CoreException(ErrorType.NOT_FOUND, "해당 사용자의 포인트 정보가 존재하지 않습니다.")
16+
);
17+
}
18+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package com.loopers.domain.point;
2+
3+
import com.loopers.support.error.CoreException;
4+
import com.loopers.support.error.ErrorType;
5+
6+
public class PointValidator {
7+
public static void validateBalance(Long balance) {
8+
if (balance == null || balance < 0) {
9+
throw new CoreException(ErrorType.BAD_REQUEST, "포인트 잔액은 0 이상이어야 합니다.");
10+
}
11+
}
12+
13+
public static void validateChargeAmount(Long amount) {
14+
if (amount == null || amount <= 0) {
15+
throw new CoreException(ErrorType.BAD_REQUEST, "충전 금액은 0 초과이어야 합니다.");
16+
}
17+
}
18+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package com.loopers.domain.user;
2+
3+
public enum Gender {
4+
MALE,
5+
FEMALE
6+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package com.loopers.domain.user;
2+
3+
import com.loopers.domain.BaseEntity;
4+
import jakarta.persistence.Entity;
5+
import jakarta.persistence.Table;
6+
import lombok.AccessLevel;
7+
import lombok.Getter;
8+
import lombok.NoArgsConstructor;
9+
10+
@Entity
11+
@Table(name = "user")
12+
@Getter
13+
@NoArgsConstructor(access = AccessLevel.PROTECTED)
14+
public class UserEntity extends BaseEntity {
15+
private String loginId;
16+
private String email;
17+
private Gender gender;
18+
private String birth;
19+
private String password;
20+
21+
public UserEntity(String loginId, String email, Gender gender, String birth, String password) {
22+
UserValidator.validateLoginId(loginId);
23+
UserValidator.validateEmail(email);
24+
UserValidator.validateBirth(birth);
25+
UserValidator.validatePassword(password);
26+
27+
this.loginId = loginId;
28+
this.email = email;
29+
this.gender = gender;
30+
this.birth = birth;
31+
this.password = password;
32+
}
33+
34+
}

0 commit comments

Comments
 (0)