Skip to content

Commit ca25f6e

Browse files
authored
Merge pull request #667 from irnd04/step2
2단계 - 수강신청(도메인 모델)
2 parents 2f6725c + d248796 commit ca25f6e

31 files changed

+692
-23
lines changed

src/main/java/nextstep/courses/domain/Course.java

+7
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ public class Course {
99

1010
private Long creatorId;
1111

12+
private final Sessions sessions = new Sessions();
13+
1214
private LocalDateTime createdAt;
1315

1416
private LocalDateTime updatedAt;
@@ -40,6 +42,11 @@ public LocalDateTime getCreatedAt() {
4042
return createdAt;
4143
}
4244

45+
public void addSession(Session session) {
46+
session.toCourse(this);
47+
sessions.add(session);
48+
}
49+
4350
@Override
4451
public String toString() {
4552
return "Course{" +
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package nextstep.courses.domain;
2+
3+
public class CoverImage {
4+
5+
private final CoverImageFileSize size;
6+
private final CoverImageType type;
7+
private final CoverImageResolution resolution;
8+
9+
CoverImage(CoverImageType type, long size, int width, int height) {
10+
this.size = new CoverImageFileSize(size);
11+
this.type = type;
12+
this.resolution = new CoverImageResolution(width, height);
13+
}
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package nextstep.courses.domain;
2+
3+
public class CoverImageFactory {
4+
5+
public static CoverImage ofGif(long size, int width, int height) {
6+
return new CoverImage(CoverImageType.GIF, size, width, height);
7+
}
8+
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package nextstep.courses.domain;
2+
3+
public class CoverImageFileSize {
4+
private static final long MAX_SIZE = 1024 * 1024; // 1MB
5+
private final long size;
6+
7+
public CoverImageFileSize(long size) {
8+
validate(size);
9+
this.size = size;
10+
}
11+
12+
private static void validate(long size) {
13+
if (size <= 0 || size > MAX_SIZE) {
14+
throw new IllegalArgumentException("이미지 크기는 0보다 크고 1MB 이하여야 합니다.");
15+
}
16+
}
17+
18+
public long getSize() {
19+
return size;
20+
}
21+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package nextstep.courses.domain;
2+
3+
public class CoverImageResolution {
4+
private static final int MIN_WIDTH = 300;
5+
private static final int MIN_HEIGHT = 200;
6+
private static final int ASPECT_RATIO_WIDTH = 3;
7+
private static final int ASPECT_RATIO_HEIGHT = 2;
8+
9+
private final int width;
10+
private final int height;
11+
12+
public CoverImageResolution(int width, int height) {
13+
validate(width, height);
14+
this.width = width;
15+
this.height = height;
16+
}
17+
18+
private static void validate(int width, int height) {
19+
validateWidthAndHeight(width, height);
20+
validateAspectRatioValid(width, height);
21+
}
22+
23+
private static void validateWidthAndHeight(int width, int height) {
24+
boolean isValid = width >= MIN_WIDTH && height >= MIN_HEIGHT;
25+
26+
if (!isValid) {
27+
throw new IllegalArgumentException("이미지의 width는 300픽셀, height는 200픽셀 이상이어야 합니다.");
28+
}
29+
}
30+
31+
private static void validateAspectRatioValid(int width, int height) {
32+
boolean isValid = width * ASPECT_RATIO_HEIGHT == height * ASPECT_RATIO_WIDTH;
33+
34+
if (!isValid) {
35+
throw new IllegalArgumentException("width와 height의 비율은 3:2여야 합니다.");
36+
}
37+
}
38+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package nextstep.courses.domain;
2+
3+
public enum CoverImageType {
4+
GIF,
5+
JPG,
6+
PNG,
7+
SVG
8+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package nextstep.courses.domain;
2+
3+
public class FreeRegistrationPolicy implements RegistrationPolicy {
4+
5+
@Override
6+
public void validateRegistration(Session session, Money paymentAmount) {
7+
// 무조건 패스
8+
}
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package nextstep.courses.domain;
2+
3+
import java.util.Objects;
4+
5+
public class Money {
6+
private final NaturalNumber value;
7+
8+
public Money(long amount) {
9+
this.value = new NaturalNumber(amount);
10+
}
11+
12+
public long getAmount() {
13+
return value.getValue();
14+
}
15+
16+
@Override
17+
public boolean equals(Object o) {
18+
if (this == o) return true;
19+
if (o == null || getClass() != o.getClass()) return false;
20+
Money money = (Money) o;
21+
return Objects.equals(value, money.value);
22+
}
23+
24+
@Override
25+
public int hashCode() {
26+
return Objects.hashCode(value);
27+
}
28+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package nextstep.courses.domain;
2+
3+
import java.util.Objects;
4+
5+
public class NaturalNumber implements Comparable<NaturalNumber> {
6+
7+
private final long value;
8+
9+
public NaturalNumber(long value) {
10+
validate(value);
11+
this.value = value;
12+
}
13+
14+
private static void validate(long value) {
15+
if (value < 0) {
16+
throw new IllegalArgumentException("0을 포함한 자연수만 허용 가능합니다.");
17+
}
18+
}
19+
20+
public long getValue() {
21+
return value;
22+
}
23+
24+
@Override
25+
public boolean equals(Object o) {
26+
if (this == o) return true;
27+
if (o == null || getClass() != o.getClass()) return false;
28+
NaturalNumber that = (NaturalNumber) o;
29+
return value == that.value;
30+
}
31+
32+
@Override
33+
public int hashCode() {
34+
return Objects.hashCode(value);
35+
}
36+
37+
@Override
38+
public String toString() {
39+
return getValue() + "";
40+
}
41+
42+
@Override
43+
public int compareTo(NaturalNumber o) {
44+
return Long.compare(getValue(), o.getValue());
45+
}
46+
47+
public int compareTo(int o) {
48+
return compareTo(new NaturalNumber(o));
49+
}
50+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package nextstep.courses.domain;
2+
3+
public class PaidRegistrationPolicy implements RegistrationPolicy {
4+
5+
private final Money sessionFee;
6+
private final NaturalNumber maxStudentCount;
7+
8+
public PaidRegistrationPolicy(int sessionFee, int maxStudentCount) {
9+
this.sessionFee = new Money(sessionFee);
10+
this.maxStudentCount = new NaturalNumber(maxStudentCount);
11+
}
12+
13+
@Override
14+
public void validateRegistration(Session session, Money paymentAmount) {
15+
if (!session.isStudentCountLessThan((int) maxStudentCount.getValue())) {
16+
throw new IllegalArgumentException("강의 최대 수강 인원을 초과할 수 없습니다.");
17+
}
18+
19+
if (!sessionFee.equals(paymentAmount)) {
20+
throw new IllegalArgumentException("수강생이 결제한 금액과 수강료가 일치할 때 수강 신청이 가능합니다.");
21+
}
22+
}
23+
24+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package nextstep.courses.domain;
2+
3+
public interface RegistrationPolicy {
4+
void validateRegistration(Session session, Money paymentAmount);
5+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package nextstep.courses.domain;
2+
3+
import nextstep.payments.domain.Payment;
4+
import nextstep.users.domain.NsUser;
5+
import nextstep.users.domain.NsUsers;
6+
7+
public class Session {
8+
private Long id;
9+
private Course course;
10+
private final NsUsers nsUsers = new NsUsers();
11+
private CoverImage coverImage;
12+
private SessionStatus sessionStatus;
13+
private RegistrationPolicy registrationPolicy;
14+
private SessionPeriod sessionPeriod;
15+
16+
Session(long id, CoverImage coverImage, SessionStatus sessionStatus, RegistrationPolicy registrationPolicy, SessionPeriod sessionPeriod) {
17+
this.id = id;
18+
this.coverImage = coverImage;
19+
this.sessionStatus = sessionStatus;
20+
this.registrationPolicy = registrationPolicy;
21+
this.sessionPeriod = sessionPeriod;
22+
}
23+
24+
public void toCourse(Course course) {
25+
this.course = course;
26+
}
27+
28+
public boolean isStudentCountLessThan(int count) {
29+
return nsUsers.getSize() < count;
30+
}
31+
32+
public Payment register(NsUser nsUser, Money paymentAmount) {
33+
if (!sessionStatus.isRegistrable()) {
34+
throw new IllegalStateException("수강신청이 불가능한 상태입니다.");
35+
}
36+
37+
registrationPolicy.validateRegistration(this, paymentAmount);
38+
39+
nsUsers.add(nsUser);
40+
41+
return new Payment("", this, nsUser, paymentAmount);
42+
}
43+
44+
45+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package nextstep.courses.domain;
2+
3+
import java.time.LocalDateTime;
4+
5+
public class SessionPeriod {
6+
7+
private final LocalDateTime startedAt;
8+
private final LocalDateTime endedAt;
9+
10+
public SessionPeriod(LocalDateTime startedAt, LocalDateTime endedAt) {
11+
this.startedAt = startedAt;
12+
this.endedAt = endedAt;
13+
}
14+
15+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package nextstep.courses.domain;
2+
3+
public enum SessionStatus {
4+
PREPARING,
5+
RECRUITING,
6+
ENDED;
7+
8+
public boolean isRegistrable() {
9+
return this == RECRUITING;
10+
}
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package nextstep.courses.domain;
2+
3+
import java.util.ArrayList;
4+
import java.util.List;
5+
6+
public class Sessions {
7+
private final List<Session> sessions;
8+
9+
public Sessions(List<Session> sessions) {
10+
this.sessions = sessions;
11+
}
12+
13+
public Sessions() {
14+
this(new ArrayList<>());
15+
}
16+
17+
public void add(Session session) {
18+
sessions.add(session);
19+
}
20+
21+
public List<Session> getSessions() {
22+
return sessions;
23+
}
24+
}

src/main/java/nextstep/payments/domain/Payment.java

+24-8
Original file line numberDiff line numberDiff line change
@@ -2,28 +2,44 @@
22

33
import java.time.LocalDateTime;
44

5+
import nextstep.courses.domain.Money;
6+
import nextstep.courses.domain.Session;
7+
import nextstep.users.domain.NsUser;
8+
59
public class Payment {
610
private String id;
711

8-
// 결제한 강의 아이디
9-
private Long sessionId;
12+
// 결제한 강의
13+
private Session session;
1014

11-
// 결제한 사용자 아이디
12-
private Long nsUserId;
15+
// 결제한 사용자
16+
private NsUser nsUser;
1317

1418
// 결제 금액
15-
private Long amount;
19+
private Money amount;
1620

1721
private LocalDateTime createdAt;
1822

1923
public Payment() {
2024
}
2125

22-
public Payment(String id, Long sessionId, Long nsUserId, Long amount) {
26+
public Payment(String id, Session session, NsUser nsUser, Money amount) {
2327
this.id = id;
24-
this.sessionId = sessionId;
25-
this.nsUserId = nsUserId;
28+
this.session = session;
29+
this.nsUser = nsUser;
2630
this.amount = amount;
2731
this.createdAt = LocalDateTime.now();
2832
}
33+
34+
public Session getSession() {
35+
return session;
36+
}
37+
38+
public NsUser getNsUser() {
39+
return nsUser;
40+
}
41+
42+
public Money getAmount() {
43+
return amount;
44+
}
2945
}

src/main/java/nextstep/qna/domain/Answer.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ public DeleteHistory delete(NsUser loginUser) {
7575
validateDelete(loginUser);
7676
this.deleted = true;
7777
this.updatedDate = LocalDateTime.now();
78-
return new DeleteHistory(ContentType.ANSWER, getId(), getWriter(), LocalDateTime.now());
78+
return DeleteHistoryFactory.ofAnswer(getId(), loginUser, LocalDateTime.now());
7979
}
8080

8181
@Override

0 commit comments

Comments
 (0)