From a28675e87c7c8df12a56e4ed935ac68c1411b7c7 Mon Sep 17 00:00:00 2001 From: hvoiunq Date: Mon, 18 Dec 2023 20:22:39 +0900 Subject: [PATCH 1/6] =?UTF-8?q?feat=20:=20=EA=B0=95=EC=9D=98=EA=B0=80=20?= =?UTF-8?q?=EC=A7=84=ED=96=89=EC=A4=91=EC=97=90=EB=8F=84=20=EB=B9=84?= =?UTF-8?q?=EB=AA=A8=EC=A7=91=EC=A4=91=EC=9D=B4=EB=A9=B4=20=EC=88=98?= =?UTF-8?q?=EA=B0=95=EC=8B=A0=EC=B2=AD=20=EB=B6=88=EA=B0=80=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- STEP4.md | 32 +++++++++++++++ .../courses/domain/image/SessionImage.java | 7 +--- .../domain/session/EnrollmentStatus.java | 3 +- .../courses/domain/session/FreeSession.java | 26 ++++++++++++ .../courses/domain/session/PaidSession.java | 25 ++++++++---- .../courses/domain/session/Session.java | 39 +++++------------- .../courses/domain/session/SessionPlan.java | 4 +- .../courses/domain/session/SessionStatus.java | 6 +-- .../courses/domain/session/SessionType.java | 7 ++++ .../JdbcSessionImageRepository.java | 2 +- .../courses/service/EnrollSessionService.java | 17 ++++++++ .../nextstep/payments/domain/Payment.java | 6 ++- .../courses/Service/EnrollSessionTest.java | 40 +++++++++++++++++++ .../nextstep/courses/domain/CourseTest.java | 7 ++-- .../courses/domain/PaidSessionTest.java | 20 ++-------- .../nextstep/courses/domain/SessionTest.java | 32 ++++++--------- .../SessionImageRepositoryTest.java | 10 ++++- .../infrastructure/SessionRepositoryTest.java | 7 +--- 18 files changed, 192 insertions(+), 98 deletions(-) create mode 100644 STEP4.md create mode 100644 src/main/java/nextstep/courses/domain/session/FreeSession.java create mode 100644 src/main/java/nextstep/courses/service/EnrollSessionService.java create mode 100644 src/test/java/nextstep/courses/Service/EnrollSessionTest.java diff --git a/STEP4.md b/STEP4.md new file mode 100644 index 000000000..ad57c7018 --- /dev/null +++ b/STEP4.md @@ -0,0 +1,32 @@ +## 변경된 기능 요구사항 +강의 수강신청은 강의 상태가 모집중일 때만 가능하다. + * 강의가 진행 중인 상태에서도 수강신청이 가능해야 한다. + * 강의 진행 상태(준비중, 진행중, 종료)와 모집 상태(비모집중, 모집중)로 상태 값을 분리해야 한다. +강의는 강의 커버 이미지 정보를 가진다. + * 강의는 하나 이상의 커버 이미지를 가질 수 있다. +강사가 승인하지 않아도 수강 신청하는 모든 사람이 수강 가능하다. + * 우아한테크코스(무료), 우아한테크캠프 Pro(유료)와 같이 선발된 인원만 수강 가능해야 한다. + * 강사는 수강신청한 사람 중 선발된 인원에 대해서만 수강 승인이 가능해야 한다. + * 강사는 수강신청한 사람 중 선발되지 않은 사람은 수강을 취소할 수 있어야 한다. + +## 프로그래밍 요구사항 +* 리팩터링할 때 컴파일 에러와 기존의 단위 테스트의 실패를 최소화하면서 점진적인 리팩터링이 가능하도록 한다. +* DB 테이블에 데이터가 존재한다는 가정하에 리팩터링해야 한다. + * 즉, 기존에 쌓인 데이터를 제거하지 않은 상태로 리팩터링 해야 한다. +### 핵심 학습 목표 +* DB 테이블이 변경될 때도 스트랭글러 패턴을 적용해 점진적인 리팩터링을 연습한다. + * 스트랭글러(교살자) 패턴 - 마틴 파울러 + * 스트랭글러 무화과 패턴 + +## STEP4 기능분해 +* 강의 수강신청은 강의 상태가 모집중일 때만 가능하다. +* [ ] 강의가 진행중이어도 모집중이면 수강신청이 가능하다. +* [X] 강의가 진행중에 비모집중이면 수강신청 불가능하다는 Exception이 발생한다. +* [ ] 강의가 준비중에 모집중이면 수강신청 가능하다. +* [ ] 강의가 준비중이어도 비모집중이면 수강신청이 불가능하다는 Exception이 발생한다. +* 강의는 강의 커버 이미지 정보를 가진다. +* [ ] 강의는 하나 이상의 커버 이미지를 갖는다. +* + +## STEP4 리팩토링 +* [ ] Session 인스턴스 변수 줄이기 \ No newline at end of file diff --git a/src/main/java/nextstep/courses/domain/image/SessionImage.java b/src/main/java/nextstep/courses/domain/image/SessionImage.java index eb02cbd96..cf1a0caba 100644 --- a/src/main/java/nextstep/courses/domain/image/SessionImage.java +++ b/src/main/java/nextstep/courses/domain/image/SessionImage.java @@ -1,6 +1,5 @@ package nextstep.courses.domain.image; -import nextstep.courses.InvalidImageFormatException; import nextstep.courses.domain.SystemTimeStamp; import nextstep.courses.domain.session.Session; @@ -19,15 +18,11 @@ public class SessionImage { public static SessionImage valueOf(long id, Session session, int size, int width, int height, String imageType) { - return new SessionImage(id, "tmp", session.getSessionId() + return new SessionImage(id, "tmp", session.getId() , new ImageFormat(size, width, height, ImageType.validateImageType(imageType)) , new SystemTimeStamp(LocalDateTime.now(), null)); } - public SessionImage(long id, String name, long sessionId, int size, int width, int height, ImageType imageType) { - this(id, name, sessionId, new ImageFormat(size, width, height, imageType), new SystemTimeStamp(LocalDateTime.now(), null)); - } - public SessionImage(long id, String name, long sessionId, ImageFormat imageFormat, SystemTimeStamp systemTimeStamp) { this.id = id; this.name = name; diff --git a/src/main/java/nextstep/courses/domain/session/EnrollmentStatus.java b/src/main/java/nextstep/courses/domain/session/EnrollmentStatus.java index 920c37da2..3b8bb9c20 100644 --- a/src/main/java/nextstep/courses/domain/session/EnrollmentStatus.java +++ b/src/main/java/nextstep/courses/domain/session/EnrollmentStatus.java @@ -5,9 +5,8 @@ import java.util.function.BiFunction; public enum EnrollmentStatus { - PREPARING("준비중"), RECRUITING("모집중"), - CLOSE("종료"); + CLOSE("비모집중"); private String status; diff --git a/src/main/java/nextstep/courses/domain/session/FreeSession.java b/src/main/java/nextstep/courses/domain/session/FreeSession.java new file mode 100644 index 000000000..adeabd769 --- /dev/null +++ b/src/main/java/nextstep/courses/domain/session/FreeSession.java @@ -0,0 +1,26 @@ +package nextstep.courses.domain.session; + +import nextstep.courses.domain.SystemTimeStamp; +import nextstep.users.domain.NsUser; + +import java.time.LocalDate; +import java.time.LocalDateTime; + +public class FreeSession extends Session { + + public static FreeSession valueOf(long id, String title, long courseId, EnrollmentStatus enrollmentStatus + , LocalDate startDate, LocalDate endDate, LocalDateTime createdAt, LocalDateTime updatedAt) { + return new FreeSession(id, title, courseId, SessionType.FREE + , new SessionPlan(enrollmentStatus, startDate, endDate) + , new SystemTimeStamp(createdAt, updatedAt)); + } + + public FreeSession(Long id, String title, long courseId, SessionType sessionType, SessionPlan sessionPlan, SystemTimeStamp systemTimeStamp) { + super(id, title, courseId, sessionType, sessionPlan, systemTimeStamp); + } + + @Override + public void signUp(NsUser student) { + super.signUp(student); + } +} diff --git a/src/main/java/nextstep/courses/domain/session/PaidSession.java b/src/main/java/nextstep/courses/domain/session/PaidSession.java index 969b65b1f..5bc6bbbab 100644 --- a/src/main/java/nextstep/courses/domain/session/PaidSession.java +++ b/src/main/java/nextstep/courses/domain/session/PaidSession.java @@ -1,7 +1,6 @@ package nextstep.courses.domain.session; import nextstep.courses.CannotSignUpException; -import nextstep.courses.domain.Course; import nextstep.courses.domain.SystemTimeStamp; import nextstep.payments.domain.Payment; import nextstep.users.domain.NsUser; @@ -32,19 +31,29 @@ public PaidSession(Long sessionId, String title, long courseId, } @Override - public void signUp(NsUser nsUser, Payment payment) throws CannotSignUpException { - validateAvailableSignUp(); - validateSessionFeeMatchingPayment(payment); - super.signUp(nsUser, payment); + public void signUp(NsUser student) { + validateAvailableStudentCount(); + validatePayInfo(student, getPayInfo(student)); + super.signUp(student); } - private void validateSessionFeeMatchingPayment(Payment payment) throws CannotSignUpException { - if (payment.isNotSamePrice(sessionFee)) { + private Payment getPayInfo(NsUser student) { + return Payment.paidOf("tmp", super.getId(), student.getId(), this.sessionFee); // 결제가 완료됐다고 가정하기 위함. + } + + private void validatePayInfo(NsUser student, Payment payment) { + if (payment.getSessionId() != this.getId()) { + throw new CannotSignUpException("해당 강의 결제이력이 없습니다."); + } + if (student.getId() != payment.getNsUserId()) { + throw new CannotSignUpException("결제자와 신청자의 정보가 일치하지 않습니다."); + } + if (payment.isNotSameSessionFee(sessionFee)) { throw new CannotSignUpException("결제금액과 수강료가 일치하지 않습니다."); } } - private void validateAvailableSignUp() throws CannotSignUpException { + private void validateAvailableStudentCount() throws CannotSignUpException { if (maxStudentCount == super.getStudentCount()) { throw new CannotSignUpException("최대 수강 인원을 초과했습니다."); } diff --git a/src/main/java/nextstep/courses/domain/session/Session.java b/src/main/java/nextstep/courses/domain/session/Session.java index f39a2d8a6..c7f26015e 100644 --- a/src/main/java/nextstep/courses/domain/session/Session.java +++ b/src/main/java/nextstep/courses/domain/session/Session.java @@ -3,35 +3,24 @@ import nextstep.courses.CannotSignUpException; import nextstep.courses.domain.SystemTimeStamp; import nextstep.courses.domain.image.SessionImage; -import nextstep.payments.domain.Payment; import nextstep.users.domain.NsUser; -import java.time.LocalDate; -import java.time.LocalDateTime; import java.util.ArrayList; import java.util.Collections; import java.util.List; public class Session { - private long sessionId; + private long id; private String title; - private long courseId; private SessionType sessionType; - private List students; private SessionImage sessionImage; + private List students; private SessionPlan sessionPlan; private SystemTimeStamp systemTimeStamp; - public static Session valueOf(long id, String title, long courseId, EnrollmentStatus enrollmentStatus - , LocalDate startDate, LocalDate endDate, LocalDateTime createdAt, LocalDateTime updatedAt) { - return new Session(id, title, courseId, SessionType.FREE - , new SessionPlan(enrollmentStatus, startDate, endDate) - , new SystemTimeStamp(createdAt, updatedAt)); - } - - public Session(Long sessionId, String title, long courseId, SessionType sessionType, SessionPlan sessionPlan, SystemTimeStamp systemTimeStamp) { - this.sessionId = sessionId; + public Session(Long id, String title, long courseId, SessionType sessionType, SessionPlan sessionPlan, SystemTimeStamp systemTimeStamp) { + this.id = id; this.title = title; this.courseId = courseId; this.students = new ArrayList<>(Collections.emptyList()); @@ -41,22 +30,12 @@ public Session(Long sessionId, String title, long courseId, SessionType sessionT this.systemTimeStamp = systemTimeStamp; } - public void signUp(NsUser student, Payment payment) { - validateSessionStatus(); - validatePayInfo(student, payment); + public void signUp(NsUser student) { + validateEnrollmentStatus(); students.add(student); } - private void validatePayInfo(NsUser student, Payment payment) { - if (payment.getSessionId() != sessionId) { - throw new CannotSignUpException("결제한 강의정보가 맞지 않습니다."); - } - if (student.getId() != payment.getNsUserId()) { - throw new CannotSignUpException("결제자와 신청자의 정보가 일치하지 않습니다."); - } - } - - private void validateSessionStatus() { + private void validateEnrollmentStatus() { if (!EnrollmentStatus.canSignUp(this.sessionPlan.getEnrollmentStatus())) { throw new CannotSignUpException("강의 모집중이 아닙니다."); } @@ -70,8 +49,8 @@ public int getStudentCount() { return students.size(); } - public Long getSessionId() { - return sessionId; + public Long getId() { + return id; } public long getCourseId() { diff --git a/src/main/java/nextstep/courses/domain/session/SessionPlan.java b/src/main/java/nextstep/courses/domain/session/SessionPlan.java index dea68cbe0..d969c9bec 100644 --- a/src/main/java/nextstep/courses/domain/session/SessionPlan.java +++ b/src/main/java/nextstep/courses/domain/session/SessionPlan.java @@ -8,9 +8,9 @@ public class SessionPlan { private LocalDate startDate; private LocalDate endDate; - public SessionPlan(EnrollmentStatus sessionStatus, LocalDate startDate, LocalDate endDate) { + public SessionPlan(EnrollmentStatus enrollmentStatus, LocalDate startDate, LocalDate endDate) { validateDate(startDate, endDate); - this.enrollmentStatus = sessionStatus; + this.enrollmentStatus = enrollmentStatus; this.startDate = startDate; this.endDate = endDate; } diff --git a/src/main/java/nextstep/courses/domain/session/SessionStatus.java b/src/main/java/nextstep/courses/domain/session/SessionStatus.java index 997f3a641..2b3f66d60 100644 --- a/src/main/java/nextstep/courses/domain/session/SessionStatus.java +++ b/src/main/java/nextstep/courses/domain/session/SessionStatus.java @@ -5,9 +5,9 @@ import java.util.function.BiFunction; public enum SessionStatus { - NOT_STARTED("강의 시작 전", (startDate, endDate) -> startDate.isAfter(LocalDate.now())), - IN_PROGRESS("강의 진행 중", (startDate, endDate) -> startDate.compareTo(LocalDate.now()) <= 0 && endDate.compareTo(LocalDate.now()) >= 0), - COMPLETED("강의 종료", (startDate, endDate) -> endDate.isBefore(LocalDate.now())); + NOT_STARTED("준비중", (startDate, endDate) -> startDate.isAfter(LocalDate.now())), + IN_PROGRESS("진행중", (startDate, endDate) -> startDate.compareTo(LocalDate.now()) <= 0 && endDate.compareTo(LocalDate.now()) >= 0), + COMPLETED("종료", (startDate, endDate) -> endDate.isBefore(LocalDate.now())); private String statusName; private BiFunction getStatus; diff --git a/src/main/java/nextstep/courses/domain/session/SessionType.java b/src/main/java/nextstep/courses/domain/session/SessionType.java index d2f81dcae..f10eb49ac 100644 --- a/src/main/java/nextstep/courses/domain/session/SessionType.java +++ b/src/main/java/nextstep/courses/domain/session/SessionType.java @@ -4,4 +4,11 @@ public enum SessionType { FREE, PAID; + public static boolean isFree(SessionType sessionType) { + return sessionType == FREE; + } + + public static boolean isPaid(SessionType sessionType) { + return sessionType == PAID; + } } diff --git a/src/main/java/nextstep/courses/infrastructure/JdbcSessionImageRepository.java b/src/main/java/nextstep/courses/infrastructure/JdbcSessionImageRepository.java index 698c68442..77d5c17db 100644 --- a/src/main/java/nextstep/courses/infrastructure/JdbcSessionImageRepository.java +++ b/src/main/java/nextstep/courses/infrastructure/JdbcSessionImageRepository.java @@ -31,7 +31,7 @@ public int save(SessionImage image) { , image.getImageFormat().getImageSize() , image.getImageFormat().getWidth() , image.getImageFormat().getHeight() - , image.getImageFormat().getImageType() + , image.getImageFormat().getImageType().name() , image.getCreatedAt() , image.getUpdatedAt()); } diff --git a/src/main/java/nextstep/courses/service/EnrollSessionService.java b/src/main/java/nextstep/courses/service/EnrollSessionService.java new file mode 100644 index 000000000..dcd48857a --- /dev/null +++ b/src/main/java/nextstep/courses/service/EnrollSessionService.java @@ -0,0 +1,17 @@ +package nextstep.courses.service; + +import nextstep.courses.domain.session.Session; +import nextstep.courses.domain.session.SessionType; +import nextstep.users.domain.NsUser; + +public class EnrollSessionService { + public void enrollSession(Session session, NsUser student) { + if (SessionType.isFree(session.getSessionType())) { + session.signUp(student); + + } else { + session.signUp(student); + } + + } +} diff --git a/src/main/java/nextstep/payments/domain/Payment.java b/src/main/java/nextstep/payments/domain/Payment.java index 6b2261f7d..f4faea90e 100644 --- a/src/main/java/nextstep/payments/domain/Payment.java +++ b/src/main/java/nextstep/payments/domain/Payment.java @@ -34,6 +34,10 @@ public Payment(String id, Long sessionId, Long nsUserId, Long amount) { this.createdAt = LocalDateTime.now(); } + public String getId() { + return id; + } + public Long getSessionId() { return sessionId; } @@ -42,7 +46,7 @@ public Long getNsUserId() { return nsUserId; } - public boolean isNotSamePrice(Long sessionFee) { + public boolean isNotSameSessionFee(Long sessionFee) { return !sessionFee.equals(amount); } } diff --git a/src/test/java/nextstep/courses/Service/EnrollSessionTest.java b/src/test/java/nextstep/courses/Service/EnrollSessionTest.java new file mode 100644 index 000000000..76de1b90b --- /dev/null +++ b/src/test/java/nextstep/courses/Service/EnrollSessionTest.java @@ -0,0 +1,40 @@ +package nextstep.courses.Service; + +import nextstep.courses.CannotSignUpException; +import nextstep.courses.domain.Course; +import nextstep.courses.domain.session.EnrollmentStatus; +import nextstep.courses.domain.session.FreeSession; +import nextstep.courses.domain.session.PaidSession; +import nextstep.courses.domain.session.Session; +import nextstep.courses.service.EnrollSessionService; +import nextstep.payments.domain.Payment; +import nextstep.users.domain.NsUser; +import nextstep.users.domain.NsUserTest; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.time.LocalDate; +import java.time.LocalDateTime; + +import static org.junit.jupiter.api.Assertions.assertThrows; + +class EnrollSessionTest { + + private Course course = new Course(1L, "TDD with java 17", 1L); + private Session session1 = PaidSession.feeOf(1L, "과제4 - 레거시 리팩토링", course.getId(), EnrollmentStatus.RECRUITING + , LocalDate.of(2023, 12, 01), LocalDate.of(2023, 12, 30) + , LocalDateTime.now(), null, 10, 10_000L); + private Session session2 = FreeSession.valueOf(1L, "과제4 - 레거시 리팩토링", course.getId(), EnrollmentStatus.CLOSE + , LocalDate.of(2023, 12, 01), LocalDate.of(2023, 12, 30) + , LocalDateTime.now(), null); + + private Payment payment = new Payment("pay1", session1.getId(), NsUserTest.JAVAJIGI.getId(), 10_000L); + + @Test + @DisplayName("강의가 진행중에 비모집중인 경우 Exception throw") + void canEnrollSessionTest() { + EnrollSessionService enrollSessionService = new EnrollSessionService(); + + assertThrows(CannotSignUpException.class, () -> enrollSessionService.enrollSession(session2, NsUserTest.SANJIGI)); + } +} diff --git a/src/test/java/nextstep/courses/domain/CourseTest.java b/src/test/java/nextstep/courses/domain/CourseTest.java index d49c1b7b8..a1f7b558d 100644 --- a/src/test/java/nextstep/courses/domain/CourseTest.java +++ b/src/test/java/nextstep/courses/domain/CourseTest.java @@ -1,6 +1,7 @@ package nextstep.courses.domain; import nextstep.courses.domain.session.EnrollmentStatus; +import nextstep.courses.domain.session.FreeSession; import nextstep.courses.domain.session.Session; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; @@ -24,9 +25,9 @@ void setUp() { @DisplayName("과정은 강의가 추가될 수 있다.") void course_AddSession_Test() { assertThat(course.getSessions().size()).isEqualTo(0); - Session session1 = Session.valueOf(1L, "과제3 - 사다리게임", course.getId() - , EnrollmentStatus.PREPARING, LocalDate.now(), LocalDate.now(), LocalDateTime.now(), LocalDateTime.now()); - Session session2 = Session.valueOf(1L, "과제4 - 레거시 리팩토링", course.getId() + Session session1 = FreeSession.valueOf(1L, "과제3 - 사다리게임", course.getId() + , EnrollmentStatus.CLOSE, LocalDate.now(), LocalDate.now(), LocalDateTime.now(), LocalDateTime.now()); + Session session2 = FreeSession.valueOf(1L, "과제4 - 레거시 리팩토링", course.getId() , EnrollmentStatus.RECRUITING, LocalDate.now(), LocalDate.now(), LocalDateTime.now(), LocalDateTime.now()); course.addSession(session1); course.addSession(session2); diff --git a/src/test/java/nextstep/courses/domain/PaidSessionTest.java b/src/test/java/nextstep/courses/domain/PaidSessionTest.java index 2caf4c8ef..ca4faf2f5 100644 --- a/src/test/java/nextstep/courses/domain/PaidSessionTest.java +++ b/src/test/java/nextstep/courses/domain/PaidSessionTest.java @@ -21,33 +21,21 @@ public class PaidSessionTest { private PaidSession paidSession = PaidSession.feeOf(1L,"step4", 1L, EnrollmentStatus.RECRUITING, LocalDate.now(), LocalDate.now(), LocalDateTime.now(), LocalDateTime.now(),1, 10_000L); - private Payment payment = Payment.paidOf("1A", paidSession.getSessionId(), NsUserTest.JAVAJIGI.getId(), 10_000L); + private Payment payment = Payment.paidOf("1A", paidSession.getId(), NsUserTest.JAVAJIGI.getId(), 10_000L); private NsUser student = NsUserTest.JAVAJIGI; @Test @DisplayName("유료 강의는 강의 최대 수강 인원을 초과할 수 없다. ") void sessionStudentTest() throws CannotSignUpException { - paidSession.signUp(student, payment); - assertThrows(CannotSignUpException.class, () -> paidSession.signUp(student, payment)); + paidSession.signUp(student); + assertThrows(CannotSignUpException.class, () -> paidSession.signUp(student)); } @Test @DisplayName("유료 강의는 수강생이 결제한 금액과 수강료가 일치할 때 수강 신청이 가능하다.") void payCheckTest() { - assertDoesNotThrow(() -> paidSession.signUp(student, payment)); - } - - @Test - @DisplayName("유료 강의는 수강생이 결제한 금액과 수강료가 일치하지 않는 경우 Exception Throw") - void payCheckExceptionTest() { - PaidSession paidSession = PaidSession.feeOf(1L,"step4", 1L, EnrollmentStatus.RECRUITING, - LocalDate.now(), LocalDate.now(), LocalDateTime.now(), LocalDateTime.now(), 2, 5_000L); - - PaymentService paymentService = new PaymentService(); - Payment payment = paymentService.paymentPaid("1"); - - assertThrows(CannotSignUpException.class, () -> paidSession.signUp(student, payment)); + assertDoesNotThrow(() -> paidSession.signUp(student)); } } diff --git a/src/test/java/nextstep/courses/domain/SessionTest.java b/src/test/java/nextstep/courses/domain/SessionTest.java index f5e4b9df6..e2fbd83db 100644 --- a/src/test/java/nextstep/courses/domain/SessionTest.java +++ b/src/test/java/nextstep/courses/domain/SessionTest.java @@ -4,6 +4,7 @@ import nextstep.courses.InvalidImageFormatException; import nextstep.courses.domain.image.SessionImage; import nextstep.courses.domain.session.EnrollmentStatus; +import nextstep.courses.domain.session.FreeSession; import nextstep.courses.domain.session.Session; import nextstep.payments.domain.Payment; import nextstep.users.domain.NsUser; @@ -28,7 +29,7 @@ public class SessionTest { void notHave_StartAndEndDate_Test() { assertThrows(IllegalArgumentException.class, - () -> Session.valueOf(1L, "과제4-리팩토링", course.getId(), EnrollmentStatus.RECRUITING + () -> FreeSession.valueOf(1L, "과제4-리팩토링", course.getId(), EnrollmentStatus.RECRUITING , null, null, LocalDateTime.now(), LocalDateTime.now())); } @@ -36,14 +37,14 @@ public class SessionTest { @DisplayName("강의는 시작일과 종료일을 가진다.") void haveDateTest() { assertDoesNotThrow(() - -> Session.valueOf(1L, "과제4-리팩토링", course.getId(), EnrollmentStatus.PREPARING + -> FreeSession.valueOf(1L, "과제4-리팩토링", course.getId(), EnrollmentStatus.CLOSE , LocalDate.of(2023, 12, 01), LocalDate.now(), LocalDateTime.now(), LocalDateTime.now())); } @Test @DisplayName("강의는 강의 커버 이미지 정보를 가진다.") void saveSessionImageTest() throws InvalidImageFormatException { - Session session = Session.valueOf(1L, "과제4 - 레거시 리팩토링", course.getId(), EnrollmentStatus.PREPARING + Session session = FreeSession.valueOf(1L, "과제4 - 레거시 리팩토링", course.getId(), EnrollmentStatus.CLOSE , LocalDate.now(), LocalDate.now(), LocalDateTime.now(), LocalDateTime.now()); assertThat(session.hasImage()).isFalse(); @@ -54,30 +55,21 @@ void saveSessionImageTest() throws InvalidImageFormatException { } @Test - @DisplayName("강의가 준비중인 경우 수강신청을 하면 Exception Throw") + @DisplayName("강의가 모집중이 아닌 경우 수강신청을 하면 Exception Throw") void cannotSignUp_ForPreparingSession_Test() { - Session session = Session.valueOf(1L, "lms", course.getId(), EnrollmentStatus.PREPARING + Session session = FreeSession.valueOf(1L, "lms", course.getId(), EnrollmentStatus.CLOSE , LocalDate.now(), LocalDate.now(), LocalDateTime.now(), LocalDateTime.now()); - Payment payment = Payment.freeOf("1", session.getSessionId(), student.getId()); - assertThrows(CannotSignUpException.class, () -> session.signUp(student, payment)); + Payment payment = Payment.freeOf("1", session.getId(), student.getId()); + assertThrows(CannotSignUpException.class, () -> session.signUp(student)); } @Test - @DisplayName("강의가 종료상태인 경우 수강신청을 하면 Exception Throw") - void cannotSignUp_ForClosedSession_Test() { - Session session = Session.valueOf(1L, "LMS", course.getId(), EnrollmentStatus.CLOSE - , LocalDate.now(), LocalDate.now(), LocalDateTime.now(), LocalDateTime.now()); - Payment payment = Payment.freeOf("1", session.getSessionId(), student.getId()); - assertThrows(CannotSignUpException.class, () -> session.signUp(student, payment)); - } - - @Test - @DisplayName("강의가 준비상태인 경우 수강신청이 가능하다.") + @DisplayName("강의가 모집중인 경우 수강신청이 가능하다.") void signUp_ForRecruitingSession_Test() throws CannotSignUpException { - Session session = Session.valueOf(1L,"lms", course.getId(), EnrollmentStatus.RECRUITING, + Session session = FreeSession.valueOf(1L,"lms", course.getId(), EnrollmentStatus.RECRUITING, LocalDate.now(), LocalDate.now(), LocalDateTime.now(), LocalDateTime.now()); - Payment payment = Payment.freeOf("1", session.getSessionId(), student.getId()); - session.signUp(student, payment); + Payment payment = Payment.freeOf("1", session.getId(), student.getId()); + session.signUp(student); assertThat(session.getStudentCount()).isEqualTo(1); } } diff --git a/src/test/java/nextstep/courses/infrastructure/SessionImageRepositoryTest.java b/src/test/java/nextstep/courses/infrastructure/SessionImageRepositoryTest.java index 607e6bcb3..719b2442b 100644 --- a/src/test/java/nextstep/courses/infrastructure/SessionImageRepositoryTest.java +++ b/src/test/java/nextstep/courses/infrastructure/SessionImageRepositoryTest.java @@ -1,9 +1,12 @@ package nextstep.courses.infrastructure; import nextstep.courses.InvalidImageFormatException; +import nextstep.courses.domain.CourseTest; +import nextstep.courses.domain.SessionTest; import nextstep.courses.domain.image.SessionImageRepository; import nextstep.courses.domain.image.ImageType; import nextstep.courses.domain.image.SessionImage; +import nextstep.courses.domain.session.*; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -13,6 +16,8 @@ import org.springframework.boot.test.autoconfigure.jdbc.JdbcTest; import org.springframework.jdbc.core.JdbcTemplate; +import java.time.LocalDate; +import java.time.LocalDateTime; import java.util.Optional; import static org.assertj.core.api.Assertions.assertThat; @@ -35,7 +40,10 @@ void setUp() { @Test @DisplayName("강의는 강의커버 이미지를 갖는다.") void save_강의커버이미지() throws InvalidImageFormatException { - SessionImage sessionImage = new SessionImage(1L, "커버이미지", 1L, 1024 * 1024, 300, 200, ImageType.PNG); + PaidSession session = PaidSession.feeOf(1L,"step4", 1L, EnrollmentStatus.RECRUITING, + LocalDate.now(), LocalDate.now(), LocalDateTime.now(), LocalDateTime.now(), 1, 10_000L); + SessionImage sessionImage = SessionImage.valueOf(1L, session + , 1024 * 1024, 300, 200, "png"); int count = sessionImageRepository.save(sessionImage); assertThat(count).isEqualTo(1); Optional savedImage = sessionImageRepository.findBySessionId(1L); diff --git a/src/test/java/nextstep/courses/infrastructure/SessionRepositoryTest.java b/src/test/java/nextstep/courses/infrastructure/SessionRepositoryTest.java index 7c35d9b91..4af7a70e1 100644 --- a/src/test/java/nextstep/courses/infrastructure/SessionRepositoryTest.java +++ b/src/test/java/nextstep/courses/infrastructure/SessionRepositoryTest.java @@ -2,10 +2,8 @@ import nextstep.courses.InvalidImageFormatException; import nextstep.courses.domain.Course; -import nextstep.courses.domain.image.ImageType; -import nextstep.courses.domain.image.SessionImage; -import nextstep.courses.domain.image.SessionImageRepository; import nextstep.courses.domain.session.EnrollmentStatus; +import nextstep.courses.domain.session.FreeSession; import nextstep.courses.domain.session.Session; import nextstep.courses.domain.session.SessionRepository; import org.junit.jupiter.api.BeforeEach; @@ -19,7 +17,6 @@ import java.time.LocalDate; import java.time.LocalDateTime; -import java.util.Optional; import static org.assertj.core.api.Assertions.assertThat; @@ -42,7 +39,7 @@ void setUp() { @DisplayName("강의 정보를 저장한다.") void save_강의_Test() throws InvalidImageFormatException { Course course = new Course(1L, "TDD with java", 1L); - Session session = Session.valueOf(1L, "LMS", course.getId(), EnrollmentStatus.CLOSE + Session session = FreeSession.valueOf(1L, "LMS", course.getId(), EnrollmentStatus.CLOSE , LocalDate.now(), LocalDate.now(), LocalDateTime.now(), LocalDateTime.now()); int count = sessionRepository.save(session); From b88f746349699e9fd202a2ecc1b34c607e48ae57 Mon Sep 17 00:00:00 2001 From: hvoiunq Date: Mon, 18 Dec 2023 20:33:55 +0900 Subject: [PATCH 2/6] =?UTF-8?q?refactor=20:=20Session=20=EC=9D=B8=EC=8A=A4?= =?UTF-8?q?=ED=84=B4=EC=8A=A4=20=EB=B3=80=EC=88=98=20=EC=A4=84=EC=9D=B4?= =?UTF-8?q?=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/nextstep/courses/domain/session/SessionInfo.java | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 src/main/java/nextstep/courses/domain/session/SessionInfo.java diff --git a/src/main/java/nextstep/courses/domain/session/SessionInfo.java b/src/main/java/nextstep/courses/domain/session/SessionInfo.java new file mode 100644 index 000000000..975dae232 --- /dev/null +++ b/src/main/java/nextstep/courses/domain/session/SessionInfo.java @@ -0,0 +1,2 @@ +package nextstep.courses.domain.session;public class SessionInfo { +} From 0d63863ce0075c361b69bdb29a928fe38271c03e Mon Sep 17 00:00:00 2001 From: hvoiunq Date: Mon, 18 Dec 2023 20:34:35 +0900 Subject: [PATCH 3/6] =?UTF-8?q?refactor=20:=20Session=20=EC=9D=B8=EC=8A=A4?= =?UTF-8?q?=ED=84=B4=EC=8A=A4=20=EB=B3=80=EC=88=98=20=EC=A4=84=EC=9D=B4?= =?UTF-8?q?=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- STEP4.md | 8 ++--- .../courses/domain/session/FreeSession.java | 6 ++-- .../courses/domain/session/PaidSession.java | 7 ++-- .../courses/domain/session/Session.java | 20 ++++------- .../courses/domain/session/SessionInfo.java | 31 ++++++++++++++++- .../infrastructure/JdbcSessionRepository.java | 4 +-- .../courses/Service/EnrollSessionTest.java | 34 ++++++++++++++++++- 7 files changed, 82 insertions(+), 28 deletions(-) diff --git a/STEP4.md b/STEP4.md index ad57c7018..f6a616452 100644 --- a/STEP4.md +++ b/STEP4.md @@ -20,13 +20,13 @@ ## STEP4 기능분해 * 강의 수강신청은 강의 상태가 모집중일 때만 가능하다. -* [ ] 강의가 진행중이어도 모집중이면 수강신청이 가능하다. +* [X] 강의가 진행중이어도 모집중이면 수강신청이 가능하다. * [X] 강의가 진행중에 비모집중이면 수강신청 불가능하다는 Exception이 발생한다. -* [ ] 강의가 준비중에 모집중이면 수강신청 가능하다. -* [ ] 강의가 준비중이어도 비모집중이면 수강신청이 불가능하다는 Exception이 발생한다. +* [X] 강의가 준비중에 모집중이면 수강신청 가능하다. +* [X] 강의가 준비중이어도 비모집중이면 수강신청이 불가능하다는 Exception이 발생한다. * 강의는 강의 커버 이미지 정보를 가진다. * [ ] 강의는 하나 이상의 커버 이미지를 갖는다. * ## STEP4 리팩토링 -* [ ] Session 인스턴스 변수 줄이기 \ No newline at end of file +* [X] Session 인스턴스 변수 줄이기 \ No newline at end of file diff --git a/src/main/java/nextstep/courses/domain/session/FreeSession.java b/src/main/java/nextstep/courses/domain/session/FreeSession.java index adeabd769..b59c81c2b 100644 --- a/src/main/java/nextstep/courses/domain/session/FreeSession.java +++ b/src/main/java/nextstep/courses/domain/session/FreeSession.java @@ -10,13 +10,13 @@ public class FreeSession extends Session { public static FreeSession valueOf(long id, String title, long courseId, EnrollmentStatus enrollmentStatus , LocalDate startDate, LocalDate endDate, LocalDateTime createdAt, LocalDateTime updatedAt) { - return new FreeSession(id, title, courseId, SessionType.FREE + return new FreeSession(new SessionInfo(id, title, courseId, SessionType.FREE) , new SessionPlan(enrollmentStatus, startDate, endDate) , new SystemTimeStamp(createdAt, updatedAt)); } - public FreeSession(Long id, String title, long courseId, SessionType sessionType, SessionPlan sessionPlan, SystemTimeStamp systemTimeStamp) { - super(id, title, courseId, sessionType, sessionPlan, systemTimeStamp); + public FreeSession(SessionInfo sessionInfo, SessionPlan sessionPlan, SystemTimeStamp systemTimeStamp) { + super(sessionInfo, sessionPlan, systemTimeStamp); } @Override diff --git a/src/main/java/nextstep/courses/domain/session/PaidSession.java b/src/main/java/nextstep/courses/domain/session/PaidSession.java index 5bc6bbbab..cb1abe6a5 100644 --- a/src/main/java/nextstep/courses/domain/session/PaidSession.java +++ b/src/main/java/nextstep/courses/domain/session/PaidSession.java @@ -16,16 +16,15 @@ public static PaidSession feeOf(long id, String title, long courseId, EnrollmentStatus enrollmentStatus, LocalDate startDate, LocalDate endDate, LocalDateTime createdAt, LocalDateTime updatedAt, int maxStudentCount, Long sessionFee) { - return new PaidSession(id, title, courseId, + return new PaidSession(new SessionInfo(id, title, courseId, SessionType.PAID), new SessionPlan(enrollmentStatus, startDate, endDate), new SystemTimeStamp(createdAt, updatedAt), maxStudentCount, sessionFee); } - public PaidSession(Long sessionId, String title, long courseId, - SessionPlan sessionPlan, SystemTimeStamp systemTimeStamp, + public PaidSession(SessionInfo sessionInfo, SessionPlan sessionPlan, SystemTimeStamp systemTimeStamp, int maxStudentCount, Long sessionFee) { - super(sessionId, title, courseId, SessionType.PAID, sessionPlan, systemTimeStamp); + super(sessionInfo, sessionPlan, systemTimeStamp); this.maxStudentCount = maxStudentCount; this.sessionFee = sessionFee; } diff --git a/src/main/java/nextstep/courses/domain/session/Session.java b/src/main/java/nextstep/courses/domain/session/Session.java index c7f26015e..77567177c 100644 --- a/src/main/java/nextstep/courses/domain/session/Session.java +++ b/src/main/java/nextstep/courses/domain/session/Session.java @@ -10,21 +10,15 @@ import java.util.List; public class Session { - private long id; - private String title; - private long courseId; - private SessionType sessionType; + private SessionInfo sessionInfo; private SessionImage sessionImage; private List students; private SessionPlan sessionPlan; private SystemTimeStamp systemTimeStamp; - public Session(Long id, String title, long courseId, SessionType sessionType, SessionPlan sessionPlan, SystemTimeStamp systemTimeStamp) { - this.id = id; - this.title = title; - this.courseId = courseId; + public Session(SessionInfo sessionInfo, SessionPlan sessionPlan, SystemTimeStamp systemTimeStamp) { + this.sessionInfo = sessionInfo; this.students = new ArrayList<>(Collections.emptyList()); - this.sessionType = sessionType; this.sessionPlan = sessionPlan; this.sessionImage = null; this.systemTimeStamp = systemTimeStamp; @@ -50,19 +44,19 @@ public int getStudentCount() { } public Long getId() { - return id; + return sessionInfo.getId(); } public long getCourseId() { - return courseId; + return sessionInfo.getCourseId(); } public String getTitle() { - return title; + return sessionInfo.getTitle(); } public SessionType getSessionType() { - return sessionType; + return sessionInfo.getSessionType(); } public SessionPlan getSessionPlan() { diff --git a/src/main/java/nextstep/courses/domain/session/SessionInfo.java b/src/main/java/nextstep/courses/domain/session/SessionInfo.java index 975dae232..4af1c8111 100644 --- a/src/main/java/nextstep/courses/domain/session/SessionInfo.java +++ b/src/main/java/nextstep/courses/domain/session/SessionInfo.java @@ -1,2 +1,31 @@ -package nextstep.courses.domain.session;public class SessionInfo { +package nextstep.courses.domain.session; + +public class SessionInfo { + private long id; + private String title; + private long courseId; + private SessionType sessionType; + + public SessionInfo(long id, String title, long courseId, SessionType sessionType) { + this.id = id; + this.title = title; + this.courseId = courseId; + this.sessionType = sessionType; + } + + public long getId() { + return id; + } + + public String getTitle() { + return title; + } + + public long getCourseId() { + return courseId; + } + + public SessionType getSessionType() { + return sessionType; + } } diff --git a/src/main/java/nextstep/courses/infrastructure/JdbcSessionRepository.java b/src/main/java/nextstep/courses/infrastructure/JdbcSessionRepository.java index 9452a4782..6fcbf2f31 100644 --- a/src/main/java/nextstep/courses/infrastructure/JdbcSessionRepository.java +++ b/src/main/java/nextstep/courses/infrastructure/JdbcSessionRepository.java @@ -50,10 +50,10 @@ public Session findBySessionId(Long id) { RowMapper rowMapper = (rs, rowNum) -> { try { return new Session( - rs.getLong(1), + new SessionInfo(rs.getLong(1), rs.getString(2), rs.getLong(3), - SessionType.valueOf(rs.getString(4)), + SessionType.valueOf(rs.getString(4))), new SessionPlan(EnrollmentStatus.valueOf(rs.getString(5)), rs.getDate(6).toLocalDate(), rs.getDate(7).toLocalDate()), diff --git a/src/test/java/nextstep/courses/Service/EnrollSessionTest.java b/src/test/java/nextstep/courses/Service/EnrollSessionTest.java index 76de1b90b..b683e0fbb 100644 --- a/src/test/java/nextstep/courses/Service/EnrollSessionTest.java +++ b/src/test/java/nextstep/courses/Service/EnrollSessionTest.java @@ -16,6 +16,7 @@ import java.time.LocalDate; import java.time.LocalDateTime; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertThrows; class EnrollSessionTest { @@ -28,13 +29,44 @@ class EnrollSessionTest { , LocalDate.of(2023, 12, 01), LocalDate.of(2023, 12, 30) , LocalDateTime.now(), null); + private Session session3 = FreeSession.valueOf(1L, "과제4 - 레거시 리팩토링", course.getId(), EnrollmentStatus.RECRUITING + , LocalDate.of(2024, 03, 01), LocalDate.of(2024, 04, 30) + , LocalDateTime.now(), null); + + private Session session4 = FreeSession.valueOf(1L, "과제4 - 레거시 리팩토링", course.getId(), EnrollmentStatus.CLOSE + , LocalDate.of(2024, 03, 01), LocalDate.of(2024, 04, 30) + , LocalDateTime.now(), null); + private Payment payment = new Payment("pay1", session1.getId(), NsUserTest.JAVAJIGI.getId(), 10_000L); @Test @DisplayName("강의가 진행중에 비모집중인 경우 Exception throw") - void canEnrollSessionTest() { + void canNotEnrollInProgressTest() { EnrollSessionService enrollSessionService = new EnrollSessionService(); assertThrows(CannotSignUpException.class, () -> enrollSessionService.enrollSession(session2, NsUserTest.SANJIGI)); } + + @Test + @DisplayName("강의가 진행중에 모집중인 경우 수강신청 가능") + void canEnrollInProgressTest() { + EnrollSessionService enrollSessionService = new EnrollSessionService(); + + assertDoesNotThrow(() -> enrollSessionService.enrollSession(session1, NsUserTest.SANJIGI)); + } + @Test + @DisplayName("강의가 준비중일 때 모집중인 경우 수강신청 가능") + void canNotEnrollNotStartedTest() { + EnrollSessionService enrollSessionService = new EnrollSessionService(); + + assertDoesNotThrow(() -> enrollSessionService.enrollSession(session3, NsUserTest.SANJIGI)); + } + + @Test + @DisplayName("강의가 준비중일 때 모집중인 경우 수강신청 가능") + void canEnrollNotStartedTest() { + EnrollSessionService enrollSessionService = new EnrollSessionService(); + + assertThrows(CannotSignUpException.class, () -> enrollSessionService.enrollSession(session4, NsUserTest.SANJIGI)); + } } From 4a20a31444caea9a7635ee93a584983b5a75cce8 Mon Sep 17 00:00:00 2001 From: hvoiunq Date: Mon, 18 Dec 2023 21:52:13 +0900 Subject: [PATCH 4/6] =?UTF-8?q?feat=20:=20student=20class=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20=EB=B0=8F=20=20=EC=88=98=EA=B0=95=EC=8B=A0=EC=B2=AD?= =?UTF-8?q?=EC=9D=98=20=EC=83=81=ED=83=9C=20=EA=B4=80=EB=A6=AC=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- STEP4.md | 6 ++-- .../{domain => common}/SystemTimeStamp.java | 2 +- .../java/nextstep/courses/domain/Course.java | 1 + .../java/nextstep/courses/domain/Student.java | 24 ++++++++++--- .../courses/domain/image/SessionImage.java | 2 +- .../courses/domain/session/FreeSession.java | 6 ++-- .../courses/domain/session/PaidSession.java | 13 +++---- .../domain/session/RegistrationState.java | 7 ++++ .../courses/domain/session/Session.java | 36 +++++++++++++------ .../courses/domain/session/Students.java | 22 ------------ .../infrastructure/JdbcCourseRepository.java | 2 +- .../JdbcSessionImageRepository.java | 2 +- .../infrastructure/JdbcSessionRepository.java | 2 +- .../courses/service/EnrollSessionService.java | 17 ++++++--- .../courses/Service/EnrollSessionTest.java | 12 ++++++- .../courses/domain/PaidSessionTest.java | 7 ++-- .../nextstep/courses/domain/SessionTest.java | 16 ++++----- 17 files changed, 109 insertions(+), 68 deletions(-) rename src/main/java/nextstep/courses/{domain => common}/SystemTimeStamp.java (93%) create mode 100644 src/main/java/nextstep/courses/domain/session/RegistrationState.java delete mode 100644 src/main/java/nextstep/courses/domain/session/Students.java diff --git a/STEP4.md b/STEP4.md index f6a616452..86d2ae5f8 100644 --- a/STEP4.md +++ b/STEP4.md @@ -25,8 +25,10 @@ * [X] 강의가 준비중에 모집중이면 수강신청 가능하다. * [X] 강의가 준비중이어도 비모집중이면 수강신청이 불가능하다는 Exception이 발생한다. * 강의는 강의 커버 이미지 정보를 가진다. -* [ ] 강의는 하나 이상의 커버 이미지를 갖는다. -* +* [X] 강의는 하나 이상의 커버 이미지를 갖는다. +* 강사가 승인하지 않아도 수강 신청하는 모든 사람이 수강 가능하다. +* [ ] 수강신청한 사람 중 선발되지 않은 수강생은 수강 취소가 된다. +* [ ] 수강신청한 사람 중 선발된 사람에 대해 수강 승인이 가능하다. ## STEP4 리팩토링 * [X] Session 인스턴스 변수 줄이기 \ No newline at end of file diff --git a/src/main/java/nextstep/courses/domain/SystemTimeStamp.java b/src/main/java/nextstep/courses/common/SystemTimeStamp.java similarity index 93% rename from src/main/java/nextstep/courses/domain/SystemTimeStamp.java rename to src/main/java/nextstep/courses/common/SystemTimeStamp.java index 184ab3e0f..92e65a4b0 100644 --- a/src/main/java/nextstep/courses/domain/SystemTimeStamp.java +++ b/src/main/java/nextstep/courses/common/SystemTimeStamp.java @@ -1,4 +1,4 @@ -package nextstep.courses.domain; +package nextstep.courses.common; import java.time.LocalDateTime; diff --git a/src/main/java/nextstep/courses/domain/Course.java b/src/main/java/nextstep/courses/domain/Course.java index 438fc2696..05f5b69df 100644 --- a/src/main/java/nextstep/courses/domain/Course.java +++ b/src/main/java/nextstep/courses/domain/Course.java @@ -1,5 +1,6 @@ package nextstep.courses.domain; +import nextstep.courses.common.SystemTimeStamp; import nextstep.courses.domain.session.Session; import nextstep.courses.domain.session.Sessions; diff --git a/src/main/java/nextstep/courses/domain/Student.java b/src/main/java/nextstep/courses/domain/Student.java index a0b400722..005f2ff5d 100644 --- a/src/main/java/nextstep/courses/domain/Student.java +++ b/src/main/java/nextstep/courses/domain/Student.java @@ -1,11 +1,27 @@ package nextstep.courses.domain; -import nextstep.courses.domain.session.Session; +import nextstep.courses.domain.session.RegistrationState; public class Student { - private long id; - private long nsUserId; + private long sessionId; + private RegistrationState registrationState; + + public Student(long nsUserId, long sessionId, RegistrationState registrationState) { + this.nsUserId = nsUserId; + this.sessionId = sessionId; + this.registrationState = registrationState; + } + + public long getNsUserId() { + return nsUserId; + } + + public long getSessionId() { + return sessionId; + } - private Session session; + public void isCanceled() { + this.registrationState = RegistrationState.CANCELED; + } } diff --git a/src/main/java/nextstep/courses/domain/image/SessionImage.java b/src/main/java/nextstep/courses/domain/image/SessionImage.java index cf1a0caba..1576899ba 100644 --- a/src/main/java/nextstep/courses/domain/image/SessionImage.java +++ b/src/main/java/nextstep/courses/domain/image/SessionImage.java @@ -1,6 +1,6 @@ package nextstep.courses.domain.image; -import nextstep.courses.domain.SystemTimeStamp; +import nextstep.courses.common.SystemTimeStamp; import nextstep.courses.domain.session.Session; import java.time.LocalDateTime; diff --git a/src/main/java/nextstep/courses/domain/session/FreeSession.java b/src/main/java/nextstep/courses/domain/session/FreeSession.java index b59c81c2b..65aa4cd16 100644 --- a/src/main/java/nextstep/courses/domain/session/FreeSession.java +++ b/src/main/java/nextstep/courses/domain/session/FreeSession.java @@ -1,7 +1,7 @@ package nextstep.courses.domain.session; -import nextstep.courses.domain.SystemTimeStamp; -import nextstep.users.domain.NsUser; +import nextstep.courses.common.SystemTimeStamp; +import nextstep.courses.domain.Student; import java.time.LocalDate; import java.time.LocalDateTime; @@ -20,7 +20,7 @@ public FreeSession(SessionInfo sessionInfo, SessionPlan sessionPlan, SystemTimeS } @Override - public void signUp(NsUser student) { + public void signUp(Student student) { super.signUp(student); } } diff --git a/src/main/java/nextstep/courses/domain/session/PaidSession.java b/src/main/java/nextstep/courses/domain/session/PaidSession.java index cb1abe6a5..e34dd29b0 100644 --- a/src/main/java/nextstep/courses/domain/session/PaidSession.java +++ b/src/main/java/nextstep/courses/domain/session/PaidSession.java @@ -1,7 +1,8 @@ package nextstep.courses.domain.session; import nextstep.courses.CannotSignUpException; -import nextstep.courses.domain.SystemTimeStamp; +import nextstep.courses.common.SystemTimeStamp; +import nextstep.courses.domain.Student; import nextstep.payments.domain.Payment; import nextstep.users.domain.NsUser; @@ -30,21 +31,21 @@ public PaidSession(SessionInfo sessionInfo, SessionPlan sessionPlan, SystemTimeS } @Override - public void signUp(NsUser student) { + public void signUp(Student student) { validateAvailableStudentCount(); validatePayInfo(student, getPayInfo(student)); super.signUp(student); } - private Payment getPayInfo(NsUser student) { - return Payment.paidOf("tmp", super.getId(), student.getId(), this.sessionFee); // 결제가 완료됐다고 가정하기 위함. + private Payment getPayInfo(Student student) { + return Payment.paidOf("tmp", super.getId(), student.getNsUserId(), this.sessionFee); // 결제가 완료됐다고 가정하기 위함. } - private void validatePayInfo(NsUser student, Payment payment) { + private void validatePayInfo(Student student, Payment payment) { if (payment.getSessionId() != this.getId()) { throw new CannotSignUpException("해당 강의 결제이력이 없습니다."); } - if (student.getId() != payment.getNsUserId()) { + if (student.getSessionId() != payment.getNsUserId()) { throw new CannotSignUpException("결제자와 신청자의 정보가 일치하지 않습니다."); } if (payment.isNotSameSessionFee(sessionFee)) { diff --git a/src/main/java/nextstep/courses/domain/session/RegistrationState.java b/src/main/java/nextstep/courses/domain/session/RegistrationState.java new file mode 100644 index 000000000..3915f96f9 --- /dev/null +++ b/src/main/java/nextstep/courses/domain/session/RegistrationState.java @@ -0,0 +1,7 @@ +package nextstep.courses.domain.session; + +public enum RegistrationState { + PENDING, // 대기중 + APPROVED, // 승인 + CANCELED // 취소 +} diff --git a/src/main/java/nextstep/courses/domain/session/Session.java b/src/main/java/nextstep/courses/domain/session/Session.java index 77567177c..fbb238e33 100644 --- a/src/main/java/nextstep/courses/domain/session/Session.java +++ b/src/main/java/nextstep/courses/domain/session/Session.java @@ -1,9 +1,10 @@ package nextstep.courses.domain.session; import nextstep.courses.CannotSignUpException; -import nextstep.courses.domain.SystemTimeStamp; +import nextstep.courses.common.SystemTimeStamp; +import nextstep.courses.domain.Student; import nextstep.courses.domain.image.SessionImage; -import nextstep.users.domain.NsUser; +import nextstep.qna.NotFoundException; import java.util.ArrayList; import java.util.Collections; @@ -11,8 +12,8 @@ public class Session { private SessionInfo sessionInfo; - private SessionImage sessionImage; - private List students; + private List sessionImage; + private List students; private SessionPlan sessionPlan; private SystemTimeStamp systemTimeStamp; @@ -20,11 +21,11 @@ public Session(SessionInfo sessionInfo, SessionPlan sessionPlan, SystemTimeStamp this.sessionInfo = sessionInfo; this.students = new ArrayList<>(Collections.emptyList()); this.sessionPlan = sessionPlan; - this.sessionImage = null; + this.sessionImage = new ArrayList<>(Collections.emptyList());; this.systemTimeStamp = systemTimeStamp; } - public void signUp(NsUser student) { + public void signUp(Student student) { validateEnrollmentStatus(); students.add(student); } @@ -36,7 +37,19 @@ private void validateEnrollmentStatus() { } public void saveImage(SessionImage sessionImage) { - this.sessionImage = sessionImage; + this.sessionImage.add(sessionImage); + } + + public void cancelSession(Student student) { + validateIsAStudent(student); + student.isCanceled(); + } + + private void validateIsAStudent(Student student) { + this.getStudents().stream() + .filter(x -> x.getNsUserId() == student.getNsUserId()) + .findFirst() + .orElseThrow(NotFoundException::new); } public int getStudentCount() { @@ -59,6 +72,10 @@ public SessionType getSessionType() { return sessionInfo.getSessionType(); } + public List getStudents() { + return students; + } + public SessionPlan getSessionPlan() { return sessionPlan; } @@ -67,8 +84,7 @@ public SystemTimeStamp getSystemTimeStamp() { return systemTimeStamp; } - public boolean hasImage() { - return !(sessionImage == null); + public int getImageCount() { + return sessionImage.size(); } - } diff --git a/src/main/java/nextstep/courses/domain/session/Students.java b/src/main/java/nextstep/courses/domain/session/Students.java deleted file mode 100644 index b9df465c5..000000000 --- a/src/main/java/nextstep/courses/domain/session/Students.java +++ /dev/null @@ -1,22 +0,0 @@ -package nextstep.courses.domain.session; - -import nextstep.users.domain.NsUser; - -import java.util.List; - -public class Students { - private final List students; - - public Students(final List students) { - this.students = students; - } - - public List getStudents() { - return students; - } - - public int size() { - return students.size(); - } - -} diff --git a/src/main/java/nextstep/courses/infrastructure/JdbcCourseRepository.java b/src/main/java/nextstep/courses/infrastructure/JdbcCourseRepository.java index 191e1bc98..243a2a192 100644 --- a/src/main/java/nextstep/courses/infrastructure/JdbcCourseRepository.java +++ b/src/main/java/nextstep/courses/infrastructure/JdbcCourseRepository.java @@ -2,7 +2,7 @@ import nextstep.courses.domain.Course; import nextstep.courses.domain.CourseRepository; -import nextstep.courses.domain.SystemTimeStamp; +import nextstep.courses.common.SystemTimeStamp; import org.springframework.jdbc.core.JdbcOperations; import org.springframework.jdbc.core.RowMapper; import org.springframework.stereotype.Repository; diff --git a/src/main/java/nextstep/courses/infrastructure/JdbcSessionImageRepository.java b/src/main/java/nextstep/courses/infrastructure/JdbcSessionImageRepository.java index 77d5c17db..6989eff14 100644 --- a/src/main/java/nextstep/courses/infrastructure/JdbcSessionImageRepository.java +++ b/src/main/java/nextstep/courses/infrastructure/JdbcSessionImageRepository.java @@ -1,7 +1,7 @@ package nextstep.courses.infrastructure; import nextstep.courses.InvalidImageFormatException; -import nextstep.courses.domain.SystemTimeStamp; +import nextstep.courses.common.SystemTimeStamp; import nextstep.courses.domain.image.ImageFormat; import nextstep.courses.domain.image.SessionImageRepository; import nextstep.courses.domain.image.ImageType; diff --git a/src/main/java/nextstep/courses/infrastructure/JdbcSessionRepository.java b/src/main/java/nextstep/courses/infrastructure/JdbcSessionRepository.java index 6fcbf2f31..a14429937 100644 --- a/src/main/java/nextstep/courses/infrastructure/JdbcSessionRepository.java +++ b/src/main/java/nextstep/courses/infrastructure/JdbcSessionRepository.java @@ -1,7 +1,7 @@ package nextstep.courses.infrastructure; import nextstep.courses.InvalidImageFormatException; -import nextstep.courses.domain.SystemTimeStamp; +import nextstep.courses.common.SystemTimeStamp; import nextstep.courses.domain.session.*; import org.springframework.jdbc.core.JdbcOperations; import org.springframework.jdbc.core.RowMapper; diff --git a/src/main/java/nextstep/courses/service/EnrollSessionService.java b/src/main/java/nextstep/courses/service/EnrollSessionService.java index dcd48857a..a16a7286d 100644 --- a/src/main/java/nextstep/courses/service/EnrollSessionService.java +++ b/src/main/java/nextstep/courses/service/EnrollSessionService.java @@ -1,17 +1,26 @@ package nextstep.courses.service; +import nextstep.courses.domain.Student; +import nextstep.courses.domain.session.RegistrationState; import nextstep.courses.domain.session.Session; import nextstep.courses.domain.session.SessionType; +import nextstep.qna.NotFoundException; import nextstep.users.domain.NsUser; public class EnrollSessionService { - public void enrollSession(Session session, NsUser student) { + public Student enrollSession(Session session, NsUser student) { + Student studentInfo = new Student(student.getId(), session.getId(), RegistrationState.PENDING); if (SessionType.isFree(session.getSessionType())) { - session.signUp(student); - + session.signUp(studentInfo); } else { - session.signUp(student); + session.signUp(studentInfo); } + return studentInfo; + } + + public void cancelSession(Session session, Student student) { + + session.cancelSession(student); } } diff --git a/src/test/java/nextstep/courses/Service/EnrollSessionTest.java b/src/test/java/nextstep/courses/Service/EnrollSessionTest.java index b683e0fbb..bfd3472cc 100644 --- a/src/test/java/nextstep/courses/Service/EnrollSessionTest.java +++ b/src/test/java/nextstep/courses/Service/EnrollSessionTest.java @@ -2,13 +2,13 @@ import nextstep.courses.CannotSignUpException; import nextstep.courses.domain.Course; +import nextstep.courses.domain.Student; import nextstep.courses.domain.session.EnrollmentStatus; import nextstep.courses.domain.session.FreeSession; import nextstep.courses.domain.session.PaidSession; import nextstep.courses.domain.session.Session; import nextstep.courses.service.EnrollSessionService; import nextstep.payments.domain.Payment; -import nextstep.users.domain.NsUser; import nextstep.users.domain.NsUserTest; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -54,6 +54,7 @@ void canEnrollInProgressTest() { assertDoesNotThrow(() -> enrollSessionService.enrollSession(session1, NsUserTest.SANJIGI)); } + @Test @DisplayName("강의가 준비중일 때 모집중인 경우 수강신청 가능") void canNotEnrollNotStartedTest() { @@ -69,4 +70,13 @@ void canEnrollNotStartedTest() { assertThrows(CannotSignUpException.class, () -> enrollSessionService.enrollSession(session4, NsUserTest.SANJIGI)); } + + @Test + @DisplayName("수강신청한 사람 중 선발되지 않은 수강생은 수강 취소가 된다.") + void cancelSessionTest() { + EnrollSessionService enrollSessionService = new EnrollSessionService(); + Student student = enrollSessionService.enrollSession(session3, NsUserTest.SANJIGI); + + enrollSessionService.cancelSession(session3, student); + } } diff --git a/src/test/java/nextstep/courses/domain/PaidSessionTest.java b/src/test/java/nextstep/courses/domain/PaidSessionTest.java index ca4faf2f5..ae7e0d103 100644 --- a/src/test/java/nextstep/courses/domain/PaidSessionTest.java +++ b/src/test/java/nextstep/courses/domain/PaidSessionTest.java @@ -3,6 +3,7 @@ import nextstep.courses.CannotSignUpException; import nextstep.courses.domain.session.EnrollmentStatus; import nextstep.courses.domain.session.PaidSession; +import nextstep.courses.domain.session.RegistrationState; import nextstep.payments.domain.Payment; import nextstep.payments.service.PaymentService; import nextstep.users.domain.NsUser; @@ -28,14 +29,14 @@ public class PaidSessionTest { @DisplayName("유료 강의는 강의 최대 수강 인원을 초과할 수 없다. ") void sessionStudentTest() throws CannotSignUpException { - paidSession.signUp(student); - assertThrows(CannotSignUpException.class, () -> paidSession.signUp(student)); + paidSession.signUp(new Student(student.getId(), paidSession.getId(), RegistrationState.PENDING)); + assertThrows(CannotSignUpException.class, () -> paidSession.signUp(new Student(student.getId(), paidSession.getId(), RegistrationState.PENDING))); } @Test @DisplayName("유료 강의는 수강생이 결제한 금액과 수강료가 일치할 때 수강 신청이 가능하다.") void payCheckTest() { - assertDoesNotThrow(() -> paidSession.signUp(student)); + assertDoesNotThrow(() -> paidSession.signUp(new Student(student.getId(), paidSession.getId(), RegistrationState.PENDING))); } } diff --git a/src/test/java/nextstep/courses/domain/SessionTest.java b/src/test/java/nextstep/courses/domain/SessionTest.java index e2fbd83db..d6d2df2ee 100644 --- a/src/test/java/nextstep/courses/domain/SessionTest.java +++ b/src/test/java/nextstep/courses/domain/SessionTest.java @@ -5,8 +5,8 @@ import nextstep.courses.domain.image.SessionImage; import nextstep.courses.domain.session.EnrollmentStatus; import nextstep.courses.domain.session.FreeSession; +import nextstep.courses.domain.session.RegistrationState; import nextstep.courses.domain.session.Session; -import nextstep.payments.domain.Payment; import nextstep.users.domain.NsUser; import nextstep.users.domain.NsUserTest; import org.junit.jupiter.api.DisplayName; @@ -46,12 +46,12 @@ void haveDateTest() { void saveSessionImageTest() throws InvalidImageFormatException { Session session = FreeSession.valueOf(1L, "과제4 - 레거시 리팩토링", course.getId(), EnrollmentStatus.CLOSE , LocalDate.now(), LocalDate.now(), LocalDateTime.now(), LocalDateTime.now()); - assertThat(session.hasImage()).isFalse(); + assertThat(session.getImageCount()).isEqualTo(0); SessionImage 강의_이미지 = SessionImage.valueOf(1L, session, 1024 * 1024, 300, 200, "jpg"); session.saveImage(강의_이미지); - assertThat(session.hasImage()).isTrue(); + assertThat(session.getImageCount()).isEqualTo(1); } @Test @@ -59,17 +59,17 @@ void saveSessionImageTest() throws InvalidImageFormatException { void cannotSignUp_ForPreparingSession_Test() { Session session = FreeSession.valueOf(1L, "lms", course.getId(), EnrollmentStatus.CLOSE , LocalDate.now(), LocalDate.now(), LocalDateTime.now(), LocalDateTime.now()); - Payment payment = Payment.freeOf("1", session.getId(), student.getId()); - assertThrows(CannotSignUpException.class, () -> session.signUp(student)); + + assertThrows(CannotSignUpException.class, () -> session.signUp(new Student(student.getId(), session.getId(), RegistrationState.PENDING))); } @Test @DisplayName("강의가 모집중인 경우 수강신청이 가능하다.") void signUp_ForRecruitingSession_Test() throws CannotSignUpException { - Session session = FreeSession.valueOf(1L,"lms", course.getId(), EnrollmentStatus.RECRUITING, + Session session = FreeSession.valueOf(1L, "lms", course.getId(), EnrollmentStatus.RECRUITING, LocalDate.now(), LocalDate.now(), LocalDateTime.now(), LocalDateTime.now()); - Payment payment = Payment.freeOf("1", session.getId(), student.getId()); - session.signUp(student); + + session.signUp(new Student(student.getId(), session.getId(), RegistrationState.PENDING)); assertThat(session.getStudentCount()).isEqualTo(1); } } From dd4ef989d11c36b4296fa14cd08cc6601e1efa20 Mon Sep 17 00:00:00 2001 From: hvoiunq Date: Mon, 18 Dec 2023 22:25:53 +0900 Subject: [PATCH 5/6] =?UTF-8?q?feat=20:=20=EC=88=98=EA=B0=95=EC=8B=A0?= =?UTF-8?q?=EC=B2=AD=20=ED=95=99=EC=83=9D=20=EC=A4=91=20=EC=84=A0=EB=B0=9C?= =?UTF-8?q?=20=EC=9C=A0=EB=AC=B4=EC=97=90=20=EB=94=B0=EB=9D=BC=20=EC=B7=A8?= =?UTF-8?q?=EC=86=8C=EC=99=80=20=EC=8A=B9=EC=9D=B8=EC=9D=B4=20=EA=B0=80?= =?UTF-8?q?=EB=8A=A5=ED=95=98=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- STEP4.md | 4 +-- .../java/nextstep/courses/domain/Student.java | 12 ++++++-- .../courses/domain/session/PaidSession.java | 2 +- .../courses/domain/session/Session.java | 23 +++++++++++---- .../courses/service/EnrollSessionService.java | 10 ++++--- .../courses/Service/EnrollSessionTest.java | 28 +++++++++++++------ 6 files changed, 57 insertions(+), 22 deletions(-) diff --git a/STEP4.md b/STEP4.md index 86d2ae5f8..f4fef2c9e 100644 --- a/STEP4.md +++ b/STEP4.md @@ -27,8 +27,8 @@ * 강의는 강의 커버 이미지 정보를 가진다. * [X] 강의는 하나 이상의 커버 이미지를 갖는다. * 강사가 승인하지 않아도 수강 신청하는 모든 사람이 수강 가능하다. -* [ ] 수강신청한 사람 중 선발되지 않은 수강생은 수강 취소가 된다. -* [ ] 수강신청한 사람 중 선발된 사람에 대해 수강 승인이 가능하다. +* [X] 수강신청한 사람 중 선발되지 않은 수강생은 수강 취소가 된다. +* [X] 수강신청한 사람 중 선발된 사람에 대해 수강 승인이 가능하다. ## STEP4 리팩토링 * [X] Session 인스턴스 변수 줄이기 \ No newline at end of file diff --git a/src/main/java/nextstep/courses/domain/Student.java b/src/main/java/nextstep/courses/domain/Student.java index 005f2ff5d..74d86dc3b 100644 --- a/src/main/java/nextstep/courses/domain/Student.java +++ b/src/main/java/nextstep/courses/domain/Student.java @@ -13,6 +13,14 @@ public Student(long nsUserId, long sessionId, RegistrationState registrationStat this.registrationState = registrationState; } + public void isCanceled() { + this.registrationState = RegistrationState.CANCELED; + } + + public void isApproved() { + this.registrationState = RegistrationState.APPROVED; + } + public long getNsUserId() { return nsUserId; } @@ -21,7 +29,7 @@ public long getSessionId() { return sessionId; } - public void isCanceled() { - this.registrationState = RegistrationState.CANCELED; + public RegistrationState getRegistrationState() { + return registrationState; } } diff --git a/src/main/java/nextstep/courses/domain/session/PaidSession.java b/src/main/java/nextstep/courses/domain/session/PaidSession.java index e34dd29b0..e2ae522f5 100644 --- a/src/main/java/nextstep/courses/domain/session/PaidSession.java +++ b/src/main/java/nextstep/courses/domain/session/PaidSession.java @@ -45,7 +45,7 @@ private void validatePayInfo(Student student, Payment payment) { if (payment.getSessionId() != this.getId()) { throw new CannotSignUpException("해당 강의 결제이력이 없습니다."); } - if (student.getSessionId() != payment.getNsUserId()) { + if (student.getNsUserId() != payment.getNsUserId()) { throw new CannotSignUpException("결제자와 신청자의 정보가 일치하지 않습니다."); } if (payment.isNotSameSessionFee(sessionFee)) { diff --git a/src/main/java/nextstep/courses/domain/session/Session.java b/src/main/java/nextstep/courses/domain/session/Session.java index fbb238e33..1691917d9 100644 --- a/src/main/java/nextstep/courses/domain/session/Session.java +++ b/src/main/java/nextstep/courses/domain/session/Session.java @@ -9,6 +9,9 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.stream.Collectors; + +import static nextstep.courses.domain.session.RegistrationState.*; public class Session { private SessionInfo sessionInfo; @@ -40,13 +43,18 @@ public void saveImage(SessionImage sessionImage) { this.sessionImage.add(sessionImage); } - public void cancelSession(Student student) { - validateIsAStudent(student); - student.isCanceled(); + public void cancelStudent(Student student) { + Student validateStudent = validateIsAStudent(student); + validateStudent.isCanceled(); + } + + public void approveStudent(Student student) { + Student validatedStudent = validateIsAStudent(student); + validatedStudent.isApproved(); } - private void validateIsAStudent(Student student) { - this.getStudents().stream() + private Student validateIsAStudent(Student student) { + return this.getAllStudents().stream() .filter(x -> x.getNsUserId() == student.getNsUserId()) .findFirst() .orElseThrow(NotFoundException::new); @@ -73,6 +81,11 @@ public SessionType getSessionType() { } public List getStudents() { + return students.stream() + .filter(student -> student.getRegistrationState() == RegistrationState.APPROVED) + .collect(Collectors.toList()); + } + public List getAllStudents() { return students; } diff --git a/src/main/java/nextstep/courses/service/EnrollSessionService.java b/src/main/java/nextstep/courses/service/EnrollSessionService.java index a16a7286d..2aba69415 100644 --- a/src/main/java/nextstep/courses/service/EnrollSessionService.java +++ b/src/main/java/nextstep/courses/service/EnrollSessionService.java @@ -4,7 +4,6 @@ import nextstep.courses.domain.session.RegistrationState; import nextstep.courses.domain.session.Session; import nextstep.courses.domain.session.SessionType; -import nextstep.qna.NotFoundException; import nextstep.users.domain.NsUser; public class EnrollSessionService { @@ -18,9 +17,12 @@ public Student enrollSession(Session session, NsUser student) { return studentInfo; } - public void cancelSession(Session session, Student student) { - - session.cancelSession(student); + public void registerStudent(Session session, Student student, Boolean approved) { + if (approved) { + session.approveStudent(student); + } else { + session.cancelStudent(student); + } } } diff --git a/src/test/java/nextstep/courses/Service/EnrollSessionTest.java b/src/test/java/nextstep/courses/Service/EnrollSessionTest.java index bfd3472cc..0d294acbc 100644 --- a/src/test/java/nextstep/courses/Service/EnrollSessionTest.java +++ b/src/test/java/nextstep/courses/Service/EnrollSessionTest.java @@ -3,12 +3,8 @@ import nextstep.courses.CannotSignUpException; import nextstep.courses.domain.Course; import nextstep.courses.domain.Student; -import nextstep.courses.domain.session.EnrollmentStatus; -import nextstep.courses.domain.session.FreeSession; -import nextstep.courses.domain.session.PaidSession; -import nextstep.courses.domain.session.Session; +import nextstep.courses.domain.session.*; import nextstep.courses.service.EnrollSessionService; -import nextstep.payments.domain.Payment; import nextstep.users.domain.NsUserTest; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -16,6 +12,7 @@ import java.time.LocalDate; import java.time.LocalDateTime; +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -37,8 +34,6 @@ class EnrollSessionTest { , LocalDate.of(2024, 03, 01), LocalDate.of(2024, 04, 30) , LocalDateTime.now(), null); - private Payment payment = new Payment("pay1", session1.getId(), NsUserTest.JAVAJIGI.getId(), 10_000L); - @Test @DisplayName("강의가 진행중에 비모집중인 경우 Exception throw") void canNotEnrollInProgressTest() { @@ -77,6 +72,23 @@ void cancelSessionTest() { EnrollSessionService enrollSessionService = new EnrollSessionService(); Student student = enrollSessionService.enrollSession(session3, NsUserTest.SANJIGI); - enrollSessionService.cancelSession(session3, student); + assertThat(student.getRegistrationState()).isEqualTo(RegistrationState.PENDING); + + enrollSessionService.registerStudent(session3, student, false); + + assertThat(student.getRegistrationState()).isEqualTo(RegistrationState.CANCELED); + } + + @Test + @DisplayName("수강신청한 사람 중 선발된 사람에 대해 수강 승인이 가능하다.") + void approveSessionTest() { + EnrollSessionService enrollSessionService = new EnrollSessionService(); + Student student = enrollSessionService.enrollSession(session3, NsUserTest.SANJIGI); + + assertThat(student.getRegistrationState()).isEqualTo(RegistrationState.PENDING); + + enrollSessionService.registerStudent(session3, student, true); + + assertThat(student.getRegistrationState()).isEqualTo(RegistrationState.APPROVED); } } From b2f5d8721ced03b09b9c76db095a43f306ef371c Mon Sep 17 00:00:00 2001 From: hvoiunq Date: Fri, 22 Dec 2023 19:40:17 +0900 Subject: [PATCH 6/6] =?UTF-8?q?refactor=20:=20session=20=EC=83=9D=EC=84=B1?= =?UTF-8?q?=EC=9E=90=EC=97=90=20NsUser=EB=A1=9C=20=EB=91=90=EA=B3=A0=20?= =?UTF-8?q?=EB=B6=88=ED=95=84=EC=9A=94=ED=95=9C=20=EC=84=9C=EB=B9=84?= =?UTF-8?q?=EC=8A=A4=20=EB=A9=94=EC=86=8C=EB=93=9C=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- STEP4.md | 7 +++- .../java/nextstep/courses/domain/Student.java | 4 +-- .../courses/domain/session/FreeSession.java | 3 +- .../courses/domain/session/PaidSession.java | 13 ++++---- .../courses/domain/session/Session.java | 19 +++++++---- .../courses/domain/session/SessionInfo.java | 33 ++++++++++++++++--- .../courses/domain/session/SessionType.java | 8 ++--- .../courses/service/EnrollSessionService.java | 13 -------- .../nextstep/payments/domain/Payment.java | 10 ++++++ .../courses/domain/PaidSessionTest.java | 8 ++--- .../nextstep/courses/domain/SessionTest.java | 4 +-- 11 files changed, 77 insertions(+), 45 deletions(-) diff --git a/STEP4.md b/STEP4.md index f4fef2c9e..5f1cc2329 100644 --- a/STEP4.md +++ b/STEP4.md @@ -31,4 +31,9 @@ * [X] 수강신청한 사람 중 선발된 사람에 대해 수강 승인이 가능하다. ## STEP4 리팩토링 -* [X] Session 인스턴스 변수 줄이기 \ No newline at end of file +* [X] Session 인스턴스 변수 줄이기 + +## STEP4 보완사항 +* [ ] List Collection 중 일급 콜렉션으로 구현하면 의미있는 필드가 있을까? 의미 있다 생각하는 필드를 일급 콜렉션으로 구현해 보는 것은 어떨까? +* [X] equals, hashCode, toString 사용하기 -> 사용하는 이유에 대해서 알아보기 +* [X] Session 생성자 타입을 NsUser로 변경한 뒤에 객체를 전달하기 \ No newline at end of file diff --git a/src/main/java/nextstep/courses/domain/Student.java b/src/main/java/nextstep/courses/domain/Student.java index 74d86dc3b..d1f5afc5f 100644 --- a/src/main/java/nextstep/courses/domain/Student.java +++ b/src/main/java/nextstep/courses/domain/Student.java @@ -13,11 +13,11 @@ public Student(long nsUserId, long sessionId, RegistrationState registrationStat this.registrationState = registrationState; } - public void isCanceled() { + public void cancel() { this.registrationState = RegistrationState.CANCELED; } - public void isApproved() { + public void approve() { this.registrationState = RegistrationState.APPROVED; } diff --git a/src/main/java/nextstep/courses/domain/session/FreeSession.java b/src/main/java/nextstep/courses/domain/session/FreeSession.java index 65aa4cd16..217f70329 100644 --- a/src/main/java/nextstep/courses/domain/session/FreeSession.java +++ b/src/main/java/nextstep/courses/domain/session/FreeSession.java @@ -2,6 +2,7 @@ import nextstep.courses.common.SystemTimeStamp; import nextstep.courses.domain.Student; +import nextstep.users.domain.NsUser; import java.time.LocalDate; import java.time.LocalDateTime; @@ -20,7 +21,7 @@ public FreeSession(SessionInfo sessionInfo, SessionPlan sessionPlan, SystemTimeS } @Override - public void signUp(Student student) { + public void signUp(NsUser student) { super.signUp(student); } } diff --git a/src/main/java/nextstep/courses/domain/session/PaidSession.java b/src/main/java/nextstep/courses/domain/session/PaidSession.java index e2ae522f5..e0ba6266e 100644 --- a/src/main/java/nextstep/courses/domain/session/PaidSession.java +++ b/src/main/java/nextstep/courses/domain/session/PaidSession.java @@ -2,7 +2,6 @@ import nextstep.courses.CannotSignUpException; import nextstep.courses.common.SystemTimeStamp; -import nextstep.courses.domain.Student; import nextstep.payments.domain.Payment; import nextstep.users.domain.NsUser; @@ -31,21 +30,21 @@ public PaidSession(SessionInfo sessionInfo, SessionPlan sessionPlan, SystemTimeS } @Override - public void signUp(Student student) { + public void signUp(NsUser student) { validateAvailableStudentCount(); validatePayInfo(student, getPayInfo(student)); super.signUp(student); } - private Payment getPayInfo(Student student) { - return Payment.paidOf("tmp", super.getId(), student.getNsUserId(), this.sessionFee); // 결제가 완료됐다고 가정하기 위함. + private Payment getPayInfo(NsUser student) { + return Payment.paidOf("tmp", super.getId(), student.getId(), this.sessionFee); // 결제가 완료됐다고 가정하기 위함. } - private void validatePayInfo(Student student, Payment payment) { - if (payment.getSessionId() != this.getId()) { + private void validatePayInfo(NsUser student, Payment payment) { + if (payment.isNotSameSessionId(this.getId())) { throw new CannotSignUpException("해당 강의 결제이력이 없습니다."); } - if (student.getNsUserId() != payment.getNsUserId()) { + if (payment.isNotSameStudentId(student.getId())) { throw new CannotSignUpException("결제자와 신청자의 정보가 일치하지 않습니다."); } if (payment.isNotSameSessionFee(sessionFee)) { diff --git a/src/main/java/nextstep/courses/domain/session/Session.java b/src/main/java/nextstep/courses/domain/session/Session.java index 1691917d9..d9df4f092 100644 --- a/src/main/java/nextstep/courses/domain/session/Session.java +++ b/src/main/java/nextstep/courses/domain/session/Session.java @@ -5,14 +5,13 @@ import nextstep.courses.domain.Student; import nextstep.courses.domain.image.SessionImage; import nextstep.qna.NotFoundException; +import nextstep.users.domain.NsUser; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.stream.Collectors; -import static nextstep.courses.domain.session.RegistrationState.*; - public class Session { private SessionInfo sessionInfo; private List sessionImage; @@ -28,9 +27,10 @@ public Session(SessionInfo sessionInfo, SessionPlan sessionPlan, SystemTimeStamp this.systemTimeStamp = systemTimeStamp; } - public void signUp(Student student) { + public void signUp(NsUser student) { + Student studentInfo = new Student(student.getId(), this.getId(), RegistrationState.PENDING); validateEnrollmentStatus(); - students.add(student); + students.add(studentInfo); } private void validateEnrollmentStatus() { @@ -45,12 +45,12 @@ public void saveImage(SessionImage sessionImage) { public void cancelStudent(Student student) { Student validateStudent = validateIsAStudent(student); - validateStudent.isCanceled(); + validateStudent.cancel(); } public void approveStudent(Student student) { Student validatedStudent = validateIsAStudent(student); - validatedStudent.isApproved(); + validatedStudent.approve(); } private Student validateIsAStudent(Student student) { @@ -100,4 +100,11 @@ public SystemTimeStamp getSystemTimeStamp() { public int getImageCount() { return sessionImage.size(); } + + public boolean isFree() { + return this.getSessionType().isFree(); + } + public boolean isPaid() { + return this.getSessionType().isPaid(); + } } diff --git a/src/main/java/nextstep/courses/domain/session/SessionInfo.java b/src/main/java/nextstep/courses/domain/session/SessionInfo.java index 4af1c8111..d158a2e44 100644 --- a/src/main/java/nextstep/courses/domain/session/SessionInfo.java +++ b/src/main/java/nextstep/courses/domain/session/SessionInfo.java @@ -1,10 +1,12 @@ package nextstep.courses.domain.session; +import java.util.Objects; + public class SessionInfo { - private long id; - private String title; - private long courseId; - private SessionType sessionType; + private final long id; + private final String title; + private final long courseId; + private final SessionType sessionType; public SessionInfo(long id, String title, long courseId, SessionType sessionType) { this.id = id; @@ -28,4 +30,27 @@ public long getCourseId() { public SessionType getSessionType() { return sessionType; } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + SessionInfo that = (SessionInfo) o; + return id == that.id && courseId == that.courseId && Objects.equals(title, that.title) && sessionType == that.sessionType; + } + + @Override + public int hashCode() { + return Objects.hash(id, title, courseId, sessionType); + } + + @Override + public String toString() { + return "SessionInfo{" + + "id=" + id + + ", title='" + title + '\'' + + ", courseId=" + courseId + + ", sessionType=" + sessionType + + '}'; + } } diff --git a/src/main/java/nextstep/courses/domain/session/SessionType.java b/src/main/java/nextstep/courses/domain/session/SessionType.java index f10eb49ac..98671d2eb 100644 --- a/src/main/java/nextstep/courses/domain/session/SessionType.java +++ b/src/main/java/nextstep/courses/domain/session/SessionType.java @@ -4,11 +4,11 @@ public enum SessionType { FREE, PAID; - public static boolean isFree(SessionType sessionType) { - return sessionType == FREE; + public boolean isFree() { + return this == FREE; } - public static boolean isPaid(SessionType sessionType) { - return sessionType == PAID; + public boolean isPaid() { + return this == PAID; } } diff --git a/src/main/java/nextstep/courses/service/EnrollSessionService.java b/src/main/java/nextstep/courses/service/EnrollSessionService.java index 2aba69415..8306e6980 100644 --- a/src/main/java/nextstep/courses/service/EnrollSessionService.java +++ b/src/main/java/nextstep/courses/service/EnrollSessionService.java @@ -1,22 +1,9 @@ package nextstep.courses.service; import nextstep.courses.domain.Student; -import nextstep.courses.domain.session.RegistrationState; import nextstep.courses.domain.session.Session; -import nextstep.courses.domain.session.SessionType; -import nextstep.users.domain.NsUser; public class EnrollSessionService { - public Student enrollSession(Session session, NsUser student) { - Student studentInfo = new Student(student.getId(), session.getId(), RegistrationState.PENDING); - if (SessionType.isFree(session.getSessionType())) { - session.signUp(studentInfo); - } else { - session.signUp(studentInfo); - } - return studentInfo; - } - public void registerStudent(Session session, Student student, Boolean approved) { if (approved) { session.approveStudent(student); diff --git a/src/main/java/nextstep/payments/domain/Payment.java b/src/main/java/nextstep/payments/domain/Payment.java index f4faea90e..ccd0c1228 100644 --- a/src/main/java/nextstep/payments/domain/Payment.java +++ b/src/main/java/nextstep/payments/domain/Payment.java @@ -1,5 +1,7 @@ package nextstep.payments.domain; +import nextstep.courses.CannotSignUpException; + import java.time.LocalDateTime; public class Payment { @@ -46,6 +48,14 @@ public Long getNsUserId() { return nsUserId; } + public boolean isNotSameSessionId(long sessionId) { + return this.sessionId != sessionId; + } + + public boolean isNotSameStudentId(long studentId) { + return this.nsUserId != studentId; + } + public boolean isNotSameSessionFee(Long sessionFee) { return !sessionFee.equals(amount); } diff --git a/src/test/java/nextstep/courses/domain/PaidSessionTest.java b/src/test/java/nextstep/courses/domain/PaidSessionTest.java index ae7e0d103..29300a7af 100644 --- a/src/test/java/nextstep/courses/domain/PaidSessionTest.java +++ b/src/test/java/nextstep/courses/domain/PaidSessionTest.java @@ -22,21 +22,19 @@ public class PaidSessionTest { private PaidSession paidSession = PaidSession.feeOf(1L,"step4", 1L, EnrollmentStatus.RECRUITING, LocalDate.now(), LocalDate.now(), LocalDateTime.now(), LocalDateTime.now(),1, 10_000L); - private Payment payment = Payment.paidOf("1A", paidSession.getId(), NsUserTest.JAVAJIGI.getId(), 10_000L); private NsUser student = NsUserTest.JAVAJIGI; @Test @DisplayName("유료 강의는 강의 최대 수강 인원을 초과할 수 없다. ") void sessionStudentTest() throws CannotSignUpException { - - paidSession.signUp(new Student(student.getId(), paidSession.getId(), RegistrationState.PENDING)); - assertThrows(CannotSignUpException.class, () -> paidSession.signUp(new Student(student.getId(), paidSession.getId(), RegistrationState.PENDING))); + paidSession.signUp(student); + assertThrows(CannotSignUpException.class, () -> paidSession.signUp(student)); } @Test @DisplayName("유료 강의는 수강생이 결제한 금액과 수강료가 일치할 때 수강 신청이 가능하다.") void payCheckTest() { - assertDoesNotThrow(() -> paidSession.signUp(new Student(student.getId(), paidSession.getId(), RegistrationState.PENDING))); + assertDoesNotThrow(() -> paidSession.signUp(student)); } } diff --git a/src/test/java/nextstep/courses/domain/SessionTest.java b/src/test/java/nextstep/courses/domain/SessionTest.java index d6d2df2ee..5f0f7efa2 100644 --- a/src/test/java/nextstep/courses/domain/SessionTest.java +++ b/src/test/java/nextstep/courses/domain/SessionTest.java @@ -60,7 +60,7 @@ void cannotSignUp_ForPreparingSession_Test() { Session session = FreeSession.valueOf(1L, "lms", course.getId(), EnrollmentStatus.CLOSE , LocalDate.now(), LocalDate.now(), LocalDateTime.now(), LocalDateTime.now()); - assertThrows(CannotSignUpException.class, () -> session.signUp(new Student(student.getId(), session.getId(), RegistrationState.PENDING))); + assertThrows(CannotSignUpException.class, () -> session.signUp(student)); } @Test @@ -69,7 +69,7 @@ void signUp_ForRecruitingSession_Test() throws CannotSignUpException { Session session = FreeSession.valueOf(1L, "lms", course.getId(), EnrollmentStatus.RECRUITING, LocalDate.now(), LocalDate.now(), LocalDateTime.now(), LocalDateTime.now()); - session.signUp(new Student(student.getId(), session.getId(), RegistrationState.PENDING)); + session.signUp(student); assertThat(session.getStudentCount()).isEqualTo(1); } }