Skip to content

Commit 7891c88

Browse files
authored
Merge pull request #35 from sylee6529/feat/user-point-test
[volume-1] 유저/포인트 도메인 구현 및 테스트 코드 작성
2 parents d5ec397 + d1c961c commit 7891c88

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+1193
-441
lines changed

apps/commerce-api/src/main/java/com/loopers/application/example/ExampleFacade.java

Lines changed: 0 additions & 17 deletions
This file was deleted.

apps/commerce-api/src/main/java/com/loopers/application/example/ExampleInfo.java

Lines changed: 0 additions & 13 deletions
This file was deleted.
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package com.loopers.application.members;
2+
3+
import com.loopers.domain.members.Gender;
4+
import com.loopers.domain.members.MemberModel;
5+
import com.loopers.domain.members.MemberService;
6+
import com.loopers.domain.points.PointService;
7+
import com.loopers.support.error.CoreException;
8+
import com.loopers.support.error.ErrorType;
9+
import lombok.RequiredArgsConstructor;
10+
import org.springframework.stereotype.Component;
11+
import org.springframework.transaction.annotation.Transactional;
12+
13+
@RequiredArgsConstructor
14+
@Component
15+
public class MemberFacade {
16+
private final MemberService memberService;
17+
private final PointService pointService;
18+
19+
@Transactional
20+
public MemberInfo registerMember(String memberId, String email, String password, String birthDate, Gender gender) {
21+
MemberModel member = memberService.registerMember(memberId, email, password, birthDate, gender);
22+
pointService.initializeMemberPoints(memberId);
23+
return MemberInfo.from(member);
24+
}
25+
26+
public MemberInfo getMemberByMemberId(String memberId) {
27+
MemberModel member = memberService.getMemberByMemberId(memberId);
28+
if (member == null) {
29+
throw new CoreException(
30+
ErrorType.NOT_FOUND,
31+
"존재하지 않는 회원입니다."
32+
);
33+
}
34+
return MemberInfo.from(member);
35+
}
36+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package com.loopers.application.members;
2+
3+
import com.loopers.domain.members.Gender;
4+
import com.loopers.domain.members.MemberModel;
5+
6+
import java.time.LocalDate;
7+
8+
public record MemberInfo(
9+
Long id,
10+
String memberId,
11+
String email,
12+
LocalDate birthDate,
13+
Gender gender
14+
) {
15+
public static MemberInfo from(MemberModel model) {
16+
return new MemberInfo(
17+
model.getId(),
18+
model.getMemberId(),
19+
model.getEmail(),
20+
model.getBirthDate(),
21+
model.getGender()
22+
);
23+
}
24+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package com.loopers.config;
2+
3+
import org.springframework.context.annotation.Bean;
4+
import org.springframework.context.annotation.Configuration;
5+
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
6+
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
7+
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
8+
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
9+
import org.springframework.security.crypto.password.PasswordEncoder;
10+
import org.springframework.security.web.SecurityFilterChain;
11+
12+
@Configuration
13+
@EnableWebSecurity
14+
public class SecurityConfig {
15+
16+
@Bean
17+
public PasswordEncoder passwordEncoder() {
18+
return new BCryptPasswordEncoder();
19+
}
20+
21+
@Bean
22+
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
23+
return http
24+
.csrf(AbstractHttpConfigurer::disable)
25+
.authorizeHttpRequests(authz -> authz.anyRequest().permitAll())
26+
.build();
27+
}
28+
}

apps/commerce-api/src/main/java/com/loopers/domain/example/ExampleModel.java

Lines changed: 0 additions & 44 deletions
This file was deleted.

apps/commerce-api/src/main/java/com/loopers/domain/example/ExampleRepository.java

Lines changed: 0 additions & 7 deletions
This file was deleted.

apps/commerce-api/src/main/java/com/loopers/domain/example/ExampleService.java

Lines changed: 0 additions & 20 deletions
This file was deleted.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package com.loopers.domain.members;
2+
3+
public enum Gender {
4+
MALE,
5+
FEMALE,
6+
OTHER
7+
}
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
package com.loopers.domain.members;
2+
3+
import com.fasterxml.jackson.annotation.JsonIgnore;
4+
import com.loopers.domain.BaseEntity;
5+
import com.loopers.support.error.CoreException;
6+
import com.loopers.support.error.ErrorType;
7+
import jakarta.persistence.Column;
8+
import jakarta.persistence.Entity;
9+
import jakarta.persistence.EnumType;
10+
import jakarta.persistence.Enumerated;
11+
import jakarta.persistence.Table;
12+
import lombok.Getter;
13+
import lombok.NoArgsConstructor;
14+
15+
import java.time.LocalDate;
16+
import java.time.format.DateTimeFormatter;
17+
import java.time.format.DateTimeParseException;
18+
import java.util.regex.Pattern;
19+
20+
@NoArgsConstructor
21+
@Getter
22+
@Entity
23+
@Table(name = "members")
24+
public class MemberModel extends BaseEntity {
25+
26+
private static final Pattern MEMBER_ID_REGEX = Pattern.compile("^[a-zA-Z0-9]{1,10}$");
27+
private static final Pattern EMAIL_REGEX = Pattern.compile("^[^@]+@[^@]+\\.[^@]+$");
28+
private static final DateTimeFormatter BIRTH_DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");
29+
30+
@Column(name = "member_id", nullable = false, unique = true, length = 10)
31+
private String memberId;
32+
33+
@Column(name = "email", nullable = false)
34+
private String email;
35+
36+
@Column(name = "birth_date", nullable = false)
37+
private LocalDate birthDate;
38+
39+
@Enumerated(EnumType.STRING)
40+
@Column(name = "gender", nullable = false)
41+
private Gender gender;
42+
43+
@Column(name = "password", nullable = false)
44+
@JsonIgnore
45+
private String password;
46+
47+
public MemberModel(String memberId, String email, String password, String birthDate, Gender gender) {
48+
validateMemberId(memberId);
49+
validateEmail(email);
50+
validateGender(gender);
51+
52+
this.memberId = memberId;
53+
this.email = email;
54+
this.password = password;
55+
this.birthDate = parseBirthDate(birthDate);
56+
this.gender = gender;
57+
}
58+
59+
private static void validateMemberId(String memberId) {
60+
if (!MEMBER_ID_REGEX.matcher(memberId).matches()) {
61+
throw new CoreException(
62+
ErrorType.BAD_REQUEST,
63+
"ID는 영문 및 숫자 10자 이내여야 합니다."
64+
);
65+
}
66+
}
67+
68+
private static void validateEmail(String email) {
69+
if (!EMAIL_REGEX.matcher(email).matches()) {
70+
throw new CoreException(
71+
ErrorType.BAD_REQUEST,
72+
"이메일은 xx@yy.zz 형식이어야 합니다."
73+
);
74+
}
75+
}
76+
77+
public static void validateGender(Gender gender) {
78+
if (gender == null) {
79+
throw new CoreException(
80+
ErrorType.BAD_REQUEST,
81+
"성별은 필수입니다."
82+
);
83+
}
84+
}
85+
86+
private static LocalDate parseBirthDate(String birthDate) {
87+
try {
88+
return LocalDate.parse(birthDate, BIRTH_DATE_FORMATTER);
89+
} catch (DateTimeParseException e) {
90+
throw new CoreException(
91+
ErrorType.BAD_REQUEST,
92+
"생년월일은 yyyy-MM-dd 형식이어야 합니다."
93+
);
94+
}
95+
}
96+
97+
}

0 commit comments

Comments
 (0)