From 6546c05eb3d7bb971037cf60c3aef5e2ac1c9d6e Mon Sep 17 00:00:00 2001 From: Sangmin Date: Fri, 12 Apr 2024 16:56:16 +0900 Subject: [PATCH 01/24] =?UTF-8?q?docs:=202=EB=8B=A8=EA=B3=84=20=EC=9A=94?= =?UTF-8?q?=EA=B5=AC=EC=82=AC=ED=95=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- TODO.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 TODO.md diff --git a/TODO.md b/TODO.md new file mode 100644 index 000000000..b9df34b53 --- /dev/null +++ b/TODO.md @@ -0,0 +1,18 @@ +# 2단계 요구사항 +### 과정 +- [ ] 과정(Course)은 기수 단위로 운영한다. +- [ ] 과정은 여러 개의 강의(Session)를 가질 수 있다. +### 강의 +- [ ] 강의는 시작일과 종료일을 가진다. +- [ ] 강의는 강의 커버 이미지 정보를 가진다. + - [ ] 이미지 크기는 1MB 이하여야 한다. + - [ ] 이미지 타입은 gif, jpg(jpeg 포함), png, svg만 허용한다. + - [ ] 이미지의 width는 300픽셀, height는 200픽셀 이상이어야 하며, width와 height의 비율은 3:2여야 한다. +- [ ] 강의는 무료 강의와 유료 강의로 나뉜다. + - [ ] 무료 강의는 최대 수강 인원 제한이 없다. + - [ ] 유료 강의는 강의 최대 수강 인원을 초과할 수 없다. + - [ ] 유료 강의는 수강생이 결제한 금액과 수강료가 일치할 때 수강 신청이 가능하다. +- [ ] 강의 상태는 준비중, 모집중, 종료 3가지 상태를 가진다. +- [ ] 강의 수강신청은 강의 상태가 모집중일 때만 가능하다. +- [ ] 유료 강의의 경우 결제는 이미 완료한 것으로 가정하고 이후 과정을 구현한다. +- [ ] 결제를 완료한 결제 정보는 payments 모듈을 통해 관리되며, 결제 정보는 Payment 객체에 담겨 반한된다. \ No newline at end of file From 0fee513e19e1467915fa10490d47a52310ec28c3 Mon Sep 17 00:00:00 2001 From: Sangmin Date: Fri, 12 Apr 2024 17:43:33 +0900 Subject: [PATCH 02/24] =?UTF-8?q?feat:=20=EA=B3=BC=EC=A0=95=EC=9D=80=20?= =?UTF-8?q?=EA=B8=B0=EC=88=98=EB=A5=BC=20=EA=B0=80=EC=A7=80=EA=B3=A0=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=EB=90=9C=EB=8B=A4=20test=20=EB=B0=8F=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/nextstep/courses/domain/Course.java | 8 ++++++-- .../nextstep/courses/domain/CourseTest.java | 18 ++++++++++++++++++ .../infrastructure/CourseRepositoryTest.java | 2 +- 3 files changed, 25 insertions(+), 3 deletions(-) create mode 100644 src/test/java/nextstep/courses/domain/CourseTest.java diff --git a/src/main/java/nextstep/courses/domain/Course.java b/src/main/java/nextstep/courses/domain/Course.java index 0f6971604..ee0d954b3 100644 --- a/src/main/java/nextstep/courses/domain/Course.java +++ b/src/main/java/nextstep/courses/domain/Course.java @@ -16,8 +16,8 @@ public class Course { public Course() { } - public Course(String title, Long creatorId) { - this(0L, title, creatorId, LocalDateTime.now(), null); + public Course(Long id, String title, Long creatorId) { + this(id, title, creatorId, LocalDateTime.now(), null); } public Course(Long id, String title, Long creatorId, LocalDateTime createdAt, LocalDateTime updatedAt) { @@ -50,4 +50,8 @@ public String toString() { ", updatedAt=" + updatedAt + '}'; } + + public Long getId() { + return id; + } } diff --git a/src/test/java/nextstep/courses/domain/CourseTest.java b/src/test/java/nextstep/courses/domain/CourseTest.java new file mode 100644 index 000000000..caf1125ab --- /dev/null +++ b/src/test/java/nextstep/courses/domain/CourseTest.java @@ -0,0 +1,18 @@ +package nextstep.courses.domain; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class CourseTest { + @DisplayName("과정은 기수를 가지고 생성된다.") + @Test + void testMethodNameHere() { + // given & when + Course course = new Course(1L, "tdd 클린코드", 1L); + + // then + assertThat(course.getId()).isEqualTo(1); + } +} diff --git a/src/test/java/nextstep/courses/infrastructure/CourseRepositoryTest.java b/src/test/java/nextstep/courses/infrastructure/CourseRepositoryTest.java index f087fc0ad..67b768072 100644 --- a/src/test/java/nextstep/courses/infrastructure/CourseRepositoryTest.java +++ b/src/test/java/nextstep/courses/infrastructure/CourseRepositoryTest.java @@ -28,7 +28,7 @@ void setUp() { @Test void crud() { - Course course = new Course("TDD, 클린 코드 with Java", 1L); + Course course = new Course(1L, "TDD, 클린 코드 with Java", 1L); int count = courseRepository.save(course); assertThat(count).isEqualTo(1); Course savedCourse = courseRepository.findById(1L); From a2616d3a2332d741fff538d1bd706d2ddb669e13 Mon Sep 17 00:00:00 2001 From: Sangmin Date: Fri, 12 Apr 2024 20:04:17 +0900 Subject: [PATCH 03/24] =?UTF-8?q?test:=20=EA=B3=BC=EC=A0=95=EC=9D=80=20?= =?UTF-8?q?=EC=97=AC=EB=9F=AC=20=EA=B0=9C=EC=9D=98=20=EA=B0=95=EC=9D=98?= =?UTF-8?q?=EB=A5=BC=20=EA=B0=80=EC=A7=80=EA=B3=A0=20=EC=83=9D=EC=84=B1?= =?UTF-8?q?=EB=90=9C=EB=8B=A4.=20fail=20test?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../nextstep/courses/domain/CourseTest.java | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/test/java/nextstep/courses/domain/CourseTest.java b/src/test/java/nextstep/courses/domain/CourseTest.java index caf1125ab..35c7f5897 100644 --- a/src/test/java/nextstep/courses/domain/CourseTest.java +++ b/src/test/java/nextstep/courses/domain/CourseTest.java @@ -3,16 +3,31 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import java.util.List; + import static org.assertj.core.api.Assertions.assertThat; public class CourseTest { @DisplayName("과정은 기수를 가지고 생성된다.") @Test - void testMethodNameHere() { + void createCourseWithCardinality() { // given & when Course course = new Course(1L, "tdd 클린코드", 1L); // then assertThat(course.getId()).isEqualTo(1); } + + @DisplayName("과정은 여러 개의 강의를 가지고 생성 된다.") + @Test + void CreateCourseWithMultipleSessions() { + // given & when + List sessions = List.of(new Session(1L, "객체지향 프로그래밍", 1L), + new Session(2L, "클래스 디자인", 1L)); + + Course course = new Course(1L, "tdd 클린코드", 1L, sessions); + + // then + assertThat(course.getSessionsSize()).isEqualTo(2); + } } From 9af8b2e59c8a6277ef233d103fc3197b28bba205 Mon Sep 17 00:00:00 2001 From: Sangmin Date: Fri, 12 Apr 2024 20:30:57 +0900 Subject: [PATCH 04/24] =?UTF-8?q?feat:=20=EA=B0=95=EC=9D=98=20=EB=8F=84?= =?UTF-8?q?=EB=A9=94=EC=9D=B8=20=EC=83=9D=EC=84=B1=20*=20=EA=B3=BC?= =?UTF-8?q?=EC=A0=95=EC=9D=80=20=EC=97=AC=EB=9F=AC=20=EA=B0=9C=EC=9D=98=20?= =?UTF-8?q?=EA=B0=95=EC=9D=98(Session)=EB=A5=BC=20=EA=B0=80=EC=A7=88=20?= =?UTF-8?q?=EC=88=98=20=EC=9E=88=EB=8B=A4.=20=EC=BC=80=EC=9D=B4=EC=8A=A4?= =?UTF-8?q?=20=ED=86=B5=EA=B3=BC=20*=20=EA=B0=95=EC=9D=98=EB=8A=94=20?= =?UTF-8?q?=EC=8B=9C=EC=9E=91=EC=9D=BC=EA=B3=BC=20=EC=A2=85=EB=A3=8C?= =?UTF-8?q?=EC=9D=BC=EC=9D=84=20=EA=B0=80=EC=A7=84=EB=8B=A4.=20=EC=BC=80?= =?UTF-8?q?=EC=9D=B4=EC=8A=A4=20=ED=86=B5=EA=B3=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- TODO.md | 6 ++--- .../java/nextstep/courses/domain/Course.java | 18 ++++++++++++- .../java/nextstep/courses/domain/Session.java | 27 +++++++++++++++++++ .../nextstep/courses/domain/CourseTest.java | 5 ++-- .../nextstep/courses/domain/SessionTest.java | 20 ++++++++++++++ 5 files changed, 70 insertions(+), 6 deletions(-) create mode 100644 src/main/java/nextstep/courses/domain/Session.java create mode 100644 src/test/java/nextstep/courses/domain/SessionTest.java diff --git a/TODO.md b/TODO.md index b9df34b53..bb7da2ef8 100644 --- a/TODO.md +++ b/TODO.md @@ -1,9 +1,9 @@ # 2단계 요구사항 ### 과정 -- [ ] 과정(Course)은 기수 단위로 운영한다. -- [ ] 과정은 여러 개의 강의(Session)를 가질 수 있다. +- [x] 과정(Course)은 기수 단위로 운영한다. +- [x] 과정은 여러 개의 강의(Session)를 가질 수 있다. ### 강의 -- [ ] 강의는 시작일과 종료일을 가진다. +- [x] 강의는 시작일과 종료일을 가진다. - [ ] 강의는 강의 커버 이미지 정보를 가진다. - [ ] 이미지 크기는 1MB 이하여야 한다. - [ ] 이미지 타입은 gif, jpg(jpeg 포함), png, svg만 허용한다. diff --git a/src/main/java/nextstep/courses/domain/Course.java b/src/main/java/nextstep/courses/domain/Course.java index ee0d954b3..099903717 100644 --- a/src/main/java/nextstep/courses/domain/Course.java +++ b/src/main/java/nextstep/courses/domain/Course.java @@ -1,6 +1,7 @@ package nextstep.courses.domain; import java.time.LocalDateTime; +import java.util.List; public class Course { private Long id; @@ -9,6 +10,8 @@ public class Course { private Long creatorId; + private List sessions; + private LocalDateTime createdAt; private LocalDateTime updatedAt; @@ -16,16 +19,25 @@ public class Course { public Course() { } + public Course(Long id, String title, Long creatorId, List sessions) { + this(id, title, creatorId, LocalDateTime.now(), null, sessions); + } + public Course(Long id, String title, Long creatorId) { - this(id, title, creatorId, LocalDateTime.now(), null); + this(id, title, creatorId, LocalDateTime.now(), null, null); } public Course(Long id, String title, Long creatorId, LocalDateTime createdAt, LocalDateTime updatedAt) { + this(id, title, creatorId, createdAt, updatedAt, null); + } + + public Course(Long id, String title, Long creatorId, LocalDateTime createdAt, LocalDateTime updatedAt, List sessions) { this.id = id; this.title = title; this.creatorId = creatorId; this.createdAt = createdAt; this.updatedAt = updatedAt; + this.sessions = sessions; } public String getTitle() { @@ -54,4 +66,8 @@ public String toString() { public Long getId() { return id; } + + public int getSessionsSize() { + return sessions.size(); + } } diff --git a/src/main/java/nextstep/courses/domain/Session.java b/src/main/java/nextstep/courses/domain/Session.java new file mode 100644 index 000000000..30556ee29 --- /dev/null +++ b/src/main/java/nextstep/courses/domain/Session.java @@ -0,0 +1,27 @@ +package nextstep.courses.domain; + +import java.time.LocalDate; + +public class Session { + + private Long id; + private String title; + private Long courseId; + private LocalDate startedAt; + private LocalDate endedAt; + + public Session(final long id, final String title, final long courseId, final LocalDate startedAt, final LocalDate endedAt) { + validateSessionDate(startedAt, endedAt); + this.id = id; + this.title = title; + this.courseId = courseId; + this.startedAt = startedAt; + this.endedAt = endedAt; + } + + private static void validateSessionDate(final LocalDate startedAt, final LocalDate endedAt) { + if (startedAt.isAfter(endedAt)) { + throw new IllegalArgumentException("강의 종료일보다 강의 시작일이 늦을 수 없습니다."); + } + } +} diff --git a/src/test/java/nextstep/courses/domain/CourseTest.java b/src/test/java/nextstep/courses/domain/CourseTest.java index 35c7f5897..544fac054 100644 --- a/src/test/java/nextstep/courses/domain/CourseTest.java +++ b/src/test/java/nextstep/courses/domain/CourseTest.java @@ -3,6 +3,7 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import java.time.LocalDate; import java.util.List; import static org.assertj.core.api.Assertions.assertThat; @@ -22,8 +23,8 @@ void createCourseWithCardinality() { @Test void CreateCourseWithMultipleSessions() { // given & when - List sessions = List.of(new Session(1L, "객체지향 프로그래밍", 1L), - new Session(2L, "클래스 디자인", 1L)); + List sessions = List.of(new Session(1L, "객체지향 프로그래밍", 1L, LocalDate.of(2024, 5, 2), LocalDate.of(2024, 5, 30)), + new Session(2L, "클래스 디자인", 1L, LocalDate.of(2024, 6, 2), LocalDate.of(2024, 2, 20))); Course course = new Course(1L, "tdd 클린코드", 1L, sessions); diff --git a/src/test/java/nextstep/courses/domain/SessionTest.java b/src/test/java/nextstep/courses/domain/SessionTest.java new file mode 100644 index 000000000..fe68e8f62 --- /dev/null +++ b/src/test/java/nextstep/courses/domain/SessionTest.java @@ -0,0 +1,20 @@ +package nextstep.courses.domain; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.time.LocalDate; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThatExceptionOfType; + +public class SessionTest { + @DisplayName("강의 종료일이 시작일보다 빠르면 예외가 발생한다.") + @Test + void notCourseEndDateEarlierThanStartDate() { + // given & when & then + assertThatExceptionOfType(IllegalArgumentException.class) + .isThrownBy(() -> { + new Session(1L, "객체지향 프로그래밍", 1L, LocalDate.of(2024, 5, 2), LocalDate.of(2024, 5, 1)); + }).withMessageMatching("강의 종료일보다 강의 시작일이 늦을 수 없습니다."); + } +} From d06b825d521532d4ccbbfb328c7151c39532266d Mon Sep 17 00:00:00 2001 From: Sangmin Date: Fri, 12 Apr 2024 21:07:43 +0900 Subject: [PATCH 05/24] =?UTF-8?q?feat:=20image=20=EB=8F=84=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/nextstep/courses/domain/Image.java | 22 +++++++++++++++++ .../nextstep/courses/domain/ImageShape.java | 24 +++++++++++++++++++ .../nextstep/courses/domain/ImageType.java | 5 ++++ .../java/nextstep/courses/domain/Session.java | 1 + 4 files changed, 52 insertions(+) create mode 100644 src/main/java/nextstep/courses/domain/Image.java create mode 100644 src/main/java/nextstep/courses/domain/ImageShape.java create mode 100644 src/main/java/nextstep/courses/domain/ImageType.java diff --git a/src/main/java/nextstep/courses/domain/Image.java b/src/main/java/nextstep/courses/domain/Image.java new file mode 100644 index 000000000..f3801cb47 --- /dev/null +++ b/src/main/java/nextstep/courses/domain/Image.java @@ -0,0 +1,22 @@ +package nextstep.courses.domain; + +public class Image { + private Long id; + private ImageType type; + private ImageShape shape; + private Integer size; + + public Image(final Long id, final ImageType type, final ImageShape shape, final Integer size) { + imageSizeValidate(size); + this.id = id; + this.type = type; + this.shape = shape; + this.size = size; + } + + private static void imageSizeValidate(final Integer size) { + if (size >= 1000000) { + throw new IllegalArgumentException("이미지 크기는 1메가 바이트를 넘을 수 없습니다."); + } + } +} diff --git a/src/main/java/nextstep/courses/domain/ImageShape.java b/src/main/java/nextstep/courses/domain/ImageShape.java new file mode 100644 index 000000000..5dab22d62 --- /dev/null +++ b/src/main/java/nextstep/courses/domain/ImageShape.java @@ -0,0 +1,24 @@ +package nextstep.courses.domain; + +public class ImageShape { + private int width; + private int height; + + public ImageShape(int width, int height) { + validateShape(width, height); + this.width = width; + this.height = height; + } + + private static void validateShape(final int width, final int height) { + if(width >= 300) { + throw new IllegalArgumentException("너비는 300px보다 커야 합니다."); + } + if(height >= 200) { + throw new IllegalArgumentException("높이는 200px보다 커야 합니다."); + } + if (width * 2 != height * 3) { + throw new IllegalArgumentException("가로 세로 비율은 3:2이어야 합니다."); + } + } +} diff --git a/src/main/java/nextstep/courses/domain/ImageType.java b/src/main/java/nextstep/courses/domain/ImageType.java new file mode 100644 index 000000000..0008de9e8 --- /dev/null +++ b/src/main/java/nextstep/courses/domain/ImageType.java @@ -0,0 +1,5 @@ +package nextstep.courses.domain; + +public enum ImageType { + GIF, JPG, JPEG, PNG, SVG +} diff --git a/src/main/java/nextstep/courses/domain/Session.java b/src/main/java/nextstep/courses/domain/Session.java index 30556ee29..ef60f9f1f 100644 --- a/src/main/java/nextstep/courses/domain/Session.java +++ b/src/main/java/nextstep/courses/domain/Session.java @@ -9,6 +9,7 @@ public class Session { private Long courseId; private LocalDate startedAt; private LocalDate endedAt; + private Image image; public Session(final long id, final String title, final long courseId, final LocalDate startedAt, final LocalDate endedAt) { validateSessionDate(startedAt, endedAt); From e2096c186f2586c4d470befc2ec59dc53fa7943f Mon Sep 17 00:00:00 2001 From: Sangmin Date: Sun, 14 Apr 2024 16:53:27 +0900 Subject: [PATCH 06/24] =?UTF-8?q?refactor:=20ImageSize=20=EB=9E=98?= =?UTF-8?q?=ED=8D=BC=ED=81=B4=EB=9E=98=EC=8A=A4=20=EC=83=9D=EC=84=B1=20?= =?UTF-8?q?=EB=B0=8F=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=84=B1=EA=B3=B5=20?= =?UTF-8?q?*=20'=EC=9D=B4=EB=AF=B8=EC=A7=80=20=ED=81=AC=EA=B8=B0=EB=8A=94?= =?UTF-8?q?=201MB=20=EC=9D=B4=ED=95=98=EC=97=AC=EC=95=BC=20=ED=95=9C?= =?UTF-8?q?=EB=8B=A4'=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=84=B1=EA=B3=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- TODO.md | 2 +- .../java/nextstep/courses/domain/Image.java | 7 ------- .../nextstep/courses/domain/ImageSize.java | 16 ++++++++++++++++ .../nextstep/courses/domain/ImageTest.java | 18 ++++++++++++++++++ 4 files changed, 35 insertions(+), 8 deletions(-) create mode 100644 src/main/java/nextstep/courses/domain/ImageSize.java create mode 100644 src/test/java/nextstep/courses/domain/ImageTest.java diff --git a/TODO.md b/TODO.md index bb7da2ef8..28018404b 100644 --- a/TODO.md +++ b/TODO.md @@ -5,7 +5,7 @@ ### 강의 - [x] 강의는 시작일과 종료일을 가진다. - [ ] 강의는 강의 커버 이미지 정보를 가진다. - - [ ] 이미지 크기는 1MB 이하여야 한다. + - [x] 이미지 크기는 1MB 이하여야 한다. - [ ] 이미지 타입은 gif, jpg(jpeg 포함), png, svg만 허용한다. - [ ] 이미지의 width는 300픽셀, height는 200픽셀 이상이어야 하며, width와 height의 비율은 3:2여야 한다. - [ ] 강의는 무료 강의와 유료 강의로 나뉜다. diff --git a/src/main/java/nextstep/courses/domain/Image.java b/src/main/java/nextstep/courses/domain/Image.java index f3801cb47..0ae8e1065 100644 --- a/src/main/java/nextstep/courses/domain/Image.java +++ b/src/main/java/nextstep/courses/domain/Image.java @@ -7,16 +7,9 @@ public class Image { private Integer size; public Image(final Long id, final ImageType type, final ImageShape shape, final Integer size) { - imageSizeValidate(size); this.id = id; this.type = type; this.shape = shape; this.size = size; } - - private static void imageSizeValidate(final Integer size) { - if (size >= 1000000) { - throw new IllegalArgumentException("이미지 크기는 1메가 바이트를 넘을 수 없습니다."); - } - } } diff --git a/src/main/java/nextstep/courses/domain/ImageSize.java b/src/main/java/nextstep/courses/domain/ImageSize.java new file mode 100644 index 000000000..ce3bdc30d --- /dev/null +++ b/src/main/java/nextstep/courses/domain/ImageSize.java @@ -0,0 +1,16 @@ +package nextstep.courses.domain; + +public class ImageSize { + private int size; + + public ImageSize(int size) { + validateSize(size); + this.size = size; + } + + private void validateSize(final int size) { + if (size >= 1000000) { + throw new IllegalArgumentException("이미지 크기는 1메가 바이트를 넘을 수 없습니다."); + } + } +} diff --git a/src/test/java/nextstep/courses/domain/ImageTest.java b/src/test/java/nextstep/courses/domain/ImageTest.java new file mode 100644 index 000000000..5b64af098 --- /dev/null +++ b/src/test/java/nextstep/courses/domain/ImageTest.java @@ -0,0 +1,18 @@ +package nextstep.courses.domain; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThatExceptionOfType; + +public class ImageTest { + @DisplayName("이미지 크기는 1MB 이하여야 한다.") + @Test + public void imageSizeLessThan1MB() { + //given & when & then + assertThatExceptionOfType(IllegalArgumentException.class) + .isThrownBy(() -> { + new ImageSize(1000000); + }).withMessageMatching("이미지 크기는 1메가 바이트를 넘을 수 없습니다."); + } +} From 19e2c38b2d25ae693e4ea9aeb63da5c375724711 Mon Sep 17 00:00:00 2001 From: Sangmin Date: Sun, 14 Apr 2024 19:59:09 +0900 Subject: [PATCH 07/24] =?UTF-8?q?refactor:=20ImageHeight,=20ImageWidth=20?= =?UTF-8?q?=EB=9E=98=ED=8D=BC=ED=81=B4=EB=9E=98=EC=8A=A4=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=20=EB=B0=8F=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=84=B1?= =?UTF-8?q?=EA=B3=B5=20*=20'=EC=9D=B4=EB=AF=B8=EC=A7=80=EC=9D=98=20width?= =?UTF-8?q?=EB=8A=94=20300=ED=94=BD=EC=85=80,=20height=EB=8A=94=20200?= =?UTF-8?q?=ED=94=BD=EC=85=80=20=EC=9D=B4=EC=83=81=EC=9D=B4=EC=96=B4?= =?UTF-8?q?=EC=95=BC=20=ED=95=98=EB=A9=B0,=20width=EC=99=80=20height?= =?UTF-8?q?=EC=9D=98=20=EB=B9=84=EC=9C=A8=EC=9D=80=203:2=EC=97=AC=EC=95=BC?= =?UTF-8?q?=20=ED=95=9C=EB=8B=A4.'=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=84=B1=EA=B3=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- TODO.md | 6 ++-- .../nextstep/courses/domain/ImageHeight.java | 20 +++++++++++++ .../nextstep/courses/domain/ImageShape.java | 22 +++++--------- .../nextstep/courses/domain/ImageWidth.java | 20 +++++++++++++ .../nextstep/courses/domain/ImageTest.java | 30 +++++++++++++++++++ 5 files changed, 81 insertions(+), 17 deletions(-) create mode 100644 src/main/java/nextstep/courses/domain/ImageHeight.java create mode 100644 src/main/java/nextstep/courses/domain/ImageWidth.java diff --git a/TODO.md b/TODO.md index 28018404b..fc05e3e1b 100644 --- a/TODO.md +++ b/TODO.md @@ -4,10 +4,10 @@ - [x] 과정은 여러 개의 강의(Session)를 가질 수 있다. ### 강의 - [x] 강의는 시작일과 종료일을 가진다. -- [ ] 강의는 강의 커버 이미지 정보를 가진다. +- [x] 강의는 강의 커버 이미지 정보를 가진다. - [x] 이미지 크기는 1MB 이하여야 한다. - - [ ] 이미지 타입은 gif, jpg(jpeg 포함), png, svg만 허용한다. - - [ ] 이미지의 width는 300픽셀, height는 200픽셀 이상이어야 하며, width와 height의 비율은 3:2여야 한다. + - [x] 이미지 타입은 gif, jpg(jpeg 포함), png, svg만 허용한다. + - [x] 이미지의 width는 300픽셀, height는 200픽셀 이상이어야 하며, width와 height의 비율은 3:2여야 한다. - [ ] 강의는 무료 강의와 유료 강의로 나뉜다. - [ ] 무료 강의는 최대 수강 인원 제한이 없다. - [ ] 유료 강의는 강의 최대 수강 인원을 초과할 수 없다. diff --git a/src/main/java/nextstep/courses/domain/ImageHeight.java b/src/main/java/nextstep/courses/domain/ImageHeight.java new file mode 100644 index 000000000..4769bd76d --- /dev/null +++ b/src/main/java/nextstep/courses/domain/ImageHeight.java @@ -0,0 +1,20 @@ +package nextstep.courses.domain; + +public class ImageHeight { + private int height; + + public ImageHeight(int height) { + validateHeight(height); + this.height = height; + } + + public int getHeight() { + return height; + } + + private void validateHeight(final int height) { + if (height < 200) { + throw new IllegalArgumentException("이미지 높이는 200px보다 커야 합니다."); + } + } +} diff --git a/src/main/java/nextstep/courses/domain/ImageShape.java b/src/main/java/nextstep/courses/domain/ImageShape.java index 5dab22d62..3b1194052 100644 --- a/src/main/java/nextstep/courses/domain/ImageShape.java +++ b/src/main/java/nextstep/courses/domain/ImageShape.java @@ -1,23 +1,17 @@ package nextstep.courses.domain; public class ImageShape { - private int width; - private int height; + private ImageWidth imageWidth; + private ImageHeight imageHeight; - public ImageShape(int width, int height) { - validateShape(width, height); - this.width = width; - this.height = height; + public ImageShape(ImageWidth imageWidth, ImageHeight imageHeight) { + validateShape(imageWidth, imageHeight); + this.imageWidth = imageWidth; + this.imageHeight = imageHeight; } - private static void validateShape(final int width, final int height) { - if(width >= 300) { - throw new IllegalArgumentException("너비는 300px보다 커야 합니다."); - } - if(height >= 200) { - throw new IllegalArgumentException("높이는 200px보다 커야 합니다."); - } - if (width * 2 != height * 3) { + private static void validateShape(final ImageWidth imageWidth, final ImageHeight imageHeight) { + if (imageWidth.getWidth() * 2 != imageHeight.getHeight() * 3) { throw new IllegalArgumentException("가로 세로 비율은 3:2이어야 합니다."); } } diff --git a/src/main/java/nextstep/courses/domain/ImageWidth.java b/src/main/java/nextstep/courses/domain/ImageWidth.java new file mode 100644 index 000000000..57f1758d9 --- /dev/null +++ b/src/main/java/nextstep/courses/domain/ImageWidth.java @@ -0,0 +1,20 @@ +package nextstep.courses.domain; + +public class ImageWidth { + private int width; + + public ImageWidth(int width) { + validateWidth(width); + this.width = width; + } + + public int getWidth() { + return width; + } + + private void validateWidth(final int width) { + if (width < 300) { + throw new IllegalArgumentException("이미지 너비는 300px보다 커야 합니다."); + } + } +} diff --git a/src/test/java/nextstep/courses/domain/ImageTest.java b/src/test/java/nextstep/courses/domain/ImageTest.java index 5b64af098..3291156df 100644 --- a/src/test/java/nextstep/courses/domain/ImageTest.java +++ b/src/test/java/nextstep/courses/domain/ImageTest.java @@ -15,4 +15,34 @@ public void imageSizeLessThan1MB() { new ImageSize(1000000); }).withMessageMatching("이미지 크기는 1메가 바이트를 넘을 수 없습니다."); } + + @DisplayName("이미지의 width는 300픽셀 이상이어야 한다.") + @Test + public void imageWidthOver300Pixel() { + //given + assertThatExceptionOfType(IllegalArgumentException.class) + .isThrownBy(() -> { + new ImageWidth(200); + }).withMessageMatching("이미지 너비는 300px보다 커야 합니다."); + } + + @DisplayName("이미지의 height는 200픽셀 이상이어야 한다.") + @Test + public void imageHeightOver200Pixel() { + //given + assertThatExceptionOfType(IllegalArgumentException.class) + .isThrownBy(() -> { + new ImageHeight(100); + }).withMessageMatching("이미지 높이는 200px보다 커야 합니다."); + } + + @DisplayName("이미지의 width와 height의 비율은 3:2여야 한다.") + @Test + public void widthAndHeightRatioEqual3To2() { + //given + assertThatExceptionOfType(IllegalArgumentException.class) + .isThrownBy(() -> { + new ImageShape(new ImageWidth(400), new ImageHeight(400)); + }).withMessageMatching("가로 세로 비율은 3:2이어야 합니다."); + } } From 0ad242c1e99d2e8ba64e38af2874443cb0df5ce9 Mon Sep 17 00:00:00 2001 From: Sangmin Date: Wed, 17 Apr 2024 09:30:40 +0900 Subject: [PATCH 08/24] =?UTF-8?q?refactor:=20image,=20session=20=EB=8F=84?= =?UTF-8?q?=EB=A9=94=EC=9D=B8=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/nextstep/{courses => image}/domain/Image.java | 2 +- .../java/nextstep/{courses => image}/domain/ImageShape.java | 2 +- .../java/nextstep/{courses => image}/domain/ImageType.java | 2 +- .../java/nextstep/{courses => sessions}/domain/Session.java | 4 +++- src/test/java/nextstep/courses/domain/CourseTest.java | 1 + .../nextstep/{courses => sessions}/domain/SessionTest.java | 2 +- 6 files changed, 8 insertions(+), 5 deletions(-) rename src/main/java/nextstep/{courses => image}/domain/Image.java (94%) rename src/main/java/nextstep/{courses => image}/domain/ImageShape.java (94%) rename src/main/java/nextstep/{courses => image}/domain/ImageType.java (61%) rename src/main/java/nextstep/{courses => sessions}/domain/Session.java (91%) rename src/test/java/nextstep/{courses => sessions}/domain/SessionTest.java (95%) diff --git a/src/main/java/nextstep/courses/domain/Image.java b/src/main/java/nextstep/image/domain/Image.java similarity index 94% rename from src/main/java/nextstep/courses/domain/Image.java rename to src/main/java/nextstep/image/domain/Image.java index f3801cb47..c678c8ad0 100644 --- a/src/main/java/nextstep/courses/domain/Image.java +++ b/src/main/java/nextstep/image/domain/Image.java @@ -1,4 +1,4 @@ -package nextstep.courses.domain; +package nextstep.image.domain; public class Image { private Long id; diff --git a/src/main/java/nextstep/courses/domain/ImageShape.java b/src/main/java/nextstep/image/domain/ImageShape.java similarity index 94% rename from src/main/java/nextstep/courses/domain/ImageShape.java rename to src/main/java/nextstep/image/domain/ImageShape.java index 5dab22d62..f82946789 100644 --- a/src/main/java/nextstep/courses/domain/ImageShape.java +++ b/src/main/java/nextstep/image/domain/ImageShape.java @@ -1,4 +1,4 @@ -package nextstep.courses.domain; +package nextstep.image.domain; public class ImageShape { private int width; diff --git a/src/main/java/nextstep/courses/domain/ImageType.java b/src/main/java/nextstep/image/domain/ImageType.java similarity index 61% rename from src/main/java/nextstep/courses/domain/ImageType.java rename to src/main/java/nextstep/image/domain/ImageType.java index 0008de9e8..d988a0f5a 100644 --- a/src/main/java/nextstep/courses/domain/ImageType.java +++ b/src/main/java/nextstep/image/domain/ImageType.java @@ -1,4 +1,4 @@ -package nextstep.courses.domain; +package nextstep.image.domain; public enum ImageType { GIF, JPG, JPEG, PNG, SVG diff --git a/src/main/java/nextstep/courses/domain/Session.java b/src/main/java/nextstep/sessions/domain/Session.java similarity index 91% rename from src/main/java/nextstep/courses/domain/Session.java rename to src/main/java/nextstep/sessions/domain/Session.java index ef60f9f1f..73734ba22 100644 --- a/src/main/java/nextstep/courses/domain/Session.java +++ b/src/main/java/nextstep/sessions/domain/Session.java @@ -1,4 +1,6 @@ -package nextstep.courses.domain; +package nextstep.sessions.domain; + +import nextstep.image.domain.Image; import java.time.LocalDate; diff --git a/src/test/java/nextstep/courses/domain/CourseTest.java b/src/test/java/nextstep/courses/domain/CourseTest.java index 544fac054..2711a39e5 100644 --- a/src/test/java/nextstep/courses/domain/CourseTest.java +++ b/src/test/java/nextstep/courses/domain/CourseTest.java @@ -1,5 +1,6 @@ package nextstep.courses.domain; +import nextstep.sessions.domain.Session; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; diff --git a/src/test/java/nextstep/courses/domain/SessionTest.java b/src/test/java/nextstep/sessions/domain/SessionTest.java similarity index 95% rename from src/test/java/nextstep/courses/domain/SessionTest.java rename to src/test/java/nextstep/sessions/domain/SessionTest.java index fe68e8f62..833182d2f 100644 --- a/src/test/java/nextstep/courses/domain/SessionTest.java +++ b/src/test/java/nextstep/sessions/domain/SessionTest.java @@ -1,4 +1,4 @@ -package nextstep.courses.domain; +package nextstep.sessions.domain; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; From c780198082193e7caeca6f688873679461308431 Mon Sep 17 00:00:00 2001 From: Sangmin Date: Thu, 18 Apr 2024 18:42:27 +0900 Subject: [PATCH 09/24] =?UTF-8?q?feat:=20Seccions=20=EC=9D=BC=EA=B8=89=20?= =?UTF-8?q?=EC=BB=AC=EB=9E=99=EC=85=98=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/nextstep/courses/domain/Course.java | 8 +++++--- .../{courses => image}/domain/ImageHeight.java | 2 +- .../{courses => image}/domain/ImageSize.java | 2 +- .../{courses => image}/domain/ImageWidth.java | 2 +- .../java/nextstep/sessions/domain/Sessions.java | 15 +++++++++++++++ .../java/nextstep/courses/domain/CourseTest.java | 6 ++++-- .../java/nextstep/courses/domain/ImageTest.java | 4 ++++ 7 files changed, 31 insertions(+), 8 deletions(-) rename src/main/java/nextstep/{courses => image}/domain/ImageHeight.java (92%) rename src/main/java/nextstep/{courses => image}/domain/ImageSize.java (91%) rename src/main/java/nextstep/{courses => image}/domain/ImageWidth.java (92%) create mode 100644 src/main/java/nextstep/sessions/domain/Sessions.java diff --git a/src/main/java/nextstep/courses/domain/Course.java b/src/main/java/nextstep/courses/domain/Course.java index 099903717..2a76ae121 100644 --- a/src/main/java/nextstep/courses/domain/Course.java +++ b/src/main/java/nextstep/courses/domain/Course.java @@ -1,5 +1,7 @@ package nextstep.courses.domain; +import nextstep.sessions.domain.Sessions; + import java.time.LocalDateTime; import java.util.List; @@ -10,7 +12,7 @@ public class Course { private Long creatorId; - private List sessions; + private Sessions sessions; private LocalDateTime createdAt; @@ -19,7 +21,7 @@ public class Course { public Course() { } - public Course(Long id, String title, Long creatorId, List sessions) { + public Course(Long id, String title, Long creatorId, Sessions sessions) { this(id, title, creatorId, LocalDateTime.now(), null, sessions); } @@ -31,7 +33,7 @@ public Course(Long id, String title, Long creatorId, LocalDateTime createdAt, Lo this(id, title, creatorId, createdAt, updatedAt, null); } - public Course(Long id, String title, Long creatorId, LocalDateTime createdAt, LocalDateTime updatedAt, List sessions) { + public Course(Long id, String title, Long creatorId, LocalDateTime createdAt, LocalDateTime updatedAt, Sessions sessions) { this.id = id; this.title = title; this.creatorId = creatorId; diff --git a/src/main/java/nextstep/courses/domain/ImageHeight.java b/src/main/java/nextstep/image/domain/ImageHeight.java similarity index 92% rename from src/main/java/nextstep/courses/domain/ImageHeight.java rename to src/main/java/nextstep/image/domain/ImageHeight.java index 4769bd76d..6b2ddc604 100644 --- a/src/main/java/nextstep/courses/domain/ImageHeight.java +++ b/src/main/java/nextstep/image/domain/ImageHeight.java @@ -1,4 +1,4 @@ -package nextstep.courses.domain; +package nextstep.image.domain; public class ImageHeight { private int height; diff --git a/src/main/java/nextstep/courses/domain/ImageSize.java b/src/main/java/nextstep/image/domain/ImageSize.java similarity index 91% rename from src/main/java/nextstep/courses/domain/ImageSize.java rename to src/main/java/nextstep/image/domain/ImageSize.java index ce3bdc30d..9eed4fa05 100644 --- a/src/main/java/nextstep/courses/domain/ImageSize.java +++ b/src/main/java/nextstep/image/domain/ImageSize.java @@ -1,4 +1,4 @@ -package nextstep.courses.domain; +package nextstep.image.domain; public class ImageSize { private int size; diff --git a/src/main/java/nextstep/courses/domain/ImageWidth.java b/src/main/java/nextstep/image/domain/ImageWidth.java similarity index 92% rename from src/main/java/nextstep/courses/domain/ImageWidth.java rename to src/main/java/nextstep/image/domain/ImageWidth.java index 57f1758d9..5be0fe3cc 100644 --- a/src/main/java/nextstep/courses/domain/ImageWidth.java +++ b/src/main/java/nextstep/image/domain/ImageWidth.java @@ -1,4 +1,4 @@ -package nextstep.courses.domain; +package nextstep.image.domain; public class ImageWidth { private int width; diff --git a/src/main/java/nextstep/sessions/domain/Sessions.java b/src/main/java/nextstep/sessions/domain/Sessions.java new file mode 100644 index 000000000..a6046693f --- /dev/null +++ b/src/main/java/nextstep/sessions/domain/Sessions.java @@ -0,0 +1,15 @@ +package nextstep.sessions.domain; + +import java.util.List; + +public class Sessions { + private List sessions; + + public Sessions(List sessions) { + this.sessions = sessions; + } + + public int size() { + return sessions.size(); + } +} diff --git a/src/test/java/nextstep/courses/domain/CourseTest.java b/src/test/java/nextstep/courses/domain/CourseTest.java index 2711a39e5..d6b2b8900 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.sessions.domain.Session; +import nextstep.sessions.domain.Sessions; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -24,9 +25,10 @@ void createCourseWithCardinality() { @Test void CreateCourseWithMultipleSessions() { // given & when - List sessions = List.of(new Session(1L, "객체지향 프로그래밍", 1L, LocalDate.of(2024, 5, 2), LocalDate.of(2024, 5, 30)), - new Session(2L, "클래스 디자인", 1L, LocalDate.of(2024, 6, 2), LocalDate.of(2024, 2, 20))); + List sessionList = List.of(new Session(1L, "객체지향 프로그래밍", 1L, LocalDate.of(2024, 5, 2), LocalDate.of(2024, 5, 30)), + new Session(2L, "클래스 디자인", 1L, LocalDate.of(2024, 6, 2), LocalDate.of(2024, 2, 20))); + Sessions sessions = new Sessions(sessionList); Course course = new Course(1L, "tdd 클린코드", 1L, sessions); // then diff --git a/src/test/java/nextstep/courses/domain/ImageTest.java b/src/test/java/nextstep/courses/domain/ImageTest.java index 3291156df..da8fdac8f 100644 --- a/src/test/java/nextstep/courses/domain/ImageTest.java +++ b/src/test/java/nextstep/courses/domain/ImageTest.java @@ -1,5 +1,9 @@ package nextstep.courses.domain; +import nextstep.image.domain.ImageHeight; +import nextstep.image.domain.ImageShape; +import nextstep.image.domain.ImageSize; +import nextstep.image.domain.ImageWidth; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; From d192c42ef4123590de60cce00a22d555775d524d Mon Sep 17 00:00:00 2001 From: Sangmin Date: Thu, 18 Apr 2024 19:23:16 +0900 Subject: [PATCH 10/24] =?UTF-8?q?feat:=20=EB=AC=B4=EB=A3=8C=EA=B0=95?= =?UTF-8?q?=EC=9D=98,=20=EC=9C=A0=EB=A3=8C=EA=B0=95=EC=9D=98=20=ED=83=80?= =?UTF-8?q?=EC=9E=85=20=EC=83=9D=EC=84=B1,=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= =?UTF-8?q?=202=EA=B0=9C=20=EC=84=B1=EA=B3=B5=20-=20'=EB=AC=B4=EB=A3=8C=20?= =?UTF-8?q?=EA=B0=95=EC=9D=98=EB=8A=94=20=EC=B5=9C=EB=8C=80=20=EC=88=98?= =?UTF-8?q?=EA=B0=95=20=EC=9D=B8=EC=9B=90=20=EC=A0=9C=ED=95=9C=EC=9D=B4=20?= =?UTF-8?q?=EC=97=86=EB=8B=A4'=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=84=B1?= =?UTF-8?q?=EA=B3=B5=20-=20'=EC=9C=A0=EB=A3=8C=20=EA=B0=95=EC=9D=98?= =?UTF-8?q?=EB=8A=94=20=EA=B0=95=EC=9D=98=20=EC=B5=9C=EB=8C=80=20=EC=88=98?= =?UTF-8?q?=EA=B0=95=20=EC=9D=B8=EC=9B=90=EC=9D=84=20=EC=B4=88=EA=B3=BC?= =?UTF-8?q?=ED=95=A0=20=EC=88=98=20=EC=97=86=EB=8B=A4.'=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=84=B1=EA=B3=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- TODO.md | 4 ++-- .../nextstep/sessions/domain/Session.java | 15 +++++++++++- .../nextstep/sessions/domain/SessionType.java | 5 ++++ .../nextstep/courses/domain/CourseTest.java | 5 ++-- .../nextstep/sessions/domain/SessionTest.java | 24 ++++++++++++++++++- 5 files changed, 47 insertions(+), 6 deletions(-) create mode 100644 src/main/java/nextstep/sessions/domain/SessionType.java diff --git a/TODO.md b/TODO.md index fc05e3e1b..74adabd2d 100644 --- a/TODO.md +++ b/TODO.md @@ -9,8 +9,8 @@ - [x] 이미지 타입은 gif, jpg(jpeg 포함), png, svg만 허용한다. - [x] 이미지의 width는 300픽셀, height는 200픽셀 이상이어야 하며, width와 height의 비율은 3:2여야 한다. - [ ] 강의는 무료 강의와 유료 강의로 나뉜다. - - [ ] 무료 강의는 최대 수강 인원 제한이 없다. - - [ ] 유료 강의는 강의 최대 수강 인원을 초과할 수 없다. + - [x] 무료 강의는 최대 수강 인원 제한이 없다. + - [x] 유료 강의는 강의 최대 수강 인원을 초과할 수 없다. - [ ] 유료 강의는 수강생이 결제한 금액과 수강료가 일치할 때 수강 신청이 가능하다. - [ ] 강의 상태는 준비중, 모집중, 종료 3가지 상태를 가진다. - [ ] 강의 수강신청은 강의 상태가 모집중일 때만 가능하다. diff --git a/src/main/java/nextstep/sessions/domain/Session.java b/src/main/java/nextstep/sessions/domain/Session.java index 73734ba22..99ed6b767 100644 --- a/src/main/java/nextstep/sessions/domain/Session.java +++ b/src/main/java/nextstep/sessions/domain/Session.java @@ -12,14 +12,27 @@ public class Session { private LocalDate startedAt; private LocalDate endedAt; private Image image; + private SessionType sessionType; + private Integer maximumAttendeeNumber; + private Integer attendeeNumber; - public Session(final long id, final String title, final long courseId, final LocalDate startedAt, final LocalDate endedAt) { + public Session(final long id, final String title, final long courseId, final LocalDate startedAt, final LocalDate endedAt, final SessionType sessionType, final int maximumAttendeeNumber, final int attendeeNumber) { validateSessionDate(startedAt, endedAt); + validateSessionMaximumAttendeeNumber(sessionType, maximumAttendeeNumber, attendeeNumber); this.id = id; this.title = title; this.courseId = courseId; this.startedAt = startedAt; this.endedAt = endedAt; + this.sessionType = sessionType; + this.maximumAttendeeNumber = maximumAttendeeNumber; + this.attendeeNumber = attendeeNumber; + } + + private void validateSessionMaximumAttendeeNumber(final SessionType sessionType, final int maximumAttendeeNumber, final int attendeeNumber) { + if (sessionType.equals(SessionType.PAID) && maximumAttendeeNumber < attendeeNumber) { + throw new IllegalArgumentException("유료 강의는 강의 최대 수강 인원을 초과할 수 없다."); + } } private static void validateSessionDate(final LocalDate startedAt, final LocalDate endedAt) { diff --git a/src/main/java/nextstep/sessions/domain/SessionType.java b/src/main/java/nextstep/sessions/domain/SessionType.java new file mode 100644 index 000000000..4b9b32b08 --- /dev/null +++ b/src/main/java/nextstep/sessions/domain/SessionType.java @@ -0,0 +1,5 @@ +package nextstep.sessions.domain; + +public enum SessionType { + FREE, PAID +} diff --git a/src/test/java/nextstep/courses/domain/CourseTest.java b/src/test/java/nextstep/courses/domain/CourseTest.java index d6b2b8900..63d570bb5 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.sessions.domain.Session; +import nextstep.sessions.domain.SessionType; import nextstep.sessions.domain.Sessions; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -26,8 +27,8 @@ void createCourseWithCardinality() { void CreateCourseWithMultipleSessions() { // given & when - List sessionList = List.of(new Session(1L, "객체지향 프로그래밍", 1L, LocalDate.of(2024, 5, 2), LocalDate.of(2024, 5, 30)), - new Session(2L, "클래스 디자인", 1L, LocalDate.of(2024, 6, 2), LocalDate.of(2024, 2, 20))); + List sessionList = List.of(new Session(1L, "객체지향 프로그래밍", 1L, LocalDate.of(2024, 5, 2), LocalDate.of(2024, 5, 30), SessionType.PAID, 10000, 100), + new Session(2L, "클래스 디자인", 1L, LocalDate.of(2024, 6, 2), LocalDate.of(2024, 2, 20), SessionType.PAID, 10000, 100)); Sessions sessions = new Sessions(sessionList); Course course = new Course(1L, "tdd 클린코드", 1L, sessions); diff --git a/src/test/java/nextstep/sessions/domain/SessionTest.java b/src/test/java/nextstep/sessions/domain/SessionTest.java index 833182d2f..d68a37dfb 100644 --- a/src/test/java/nextstep/sessions/domain/SessionTest.java +++ b/src/test/java/nextstep/sessions/domain/SessionTest.java @@ -5,6 +5,7 @@ import java.time.LocalDate; +import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.AssertionsForClassTypes.assertThatExceptionOfType; public class SessionTest { @@ -14,7 +15,28 @@ void notCourseEndDateEarlierThanStartDate() { // given & when & then assertThatExceptionOfType(IllegalArgumentException.class) .isThrownBy(() -> { - new Session(1L, "객체지향 프로그래밍", 1L, LocalDate.of(2024, 5, 2), LocalDate.of(2024, 5, 1)); + new Session(1L, "객체지향 프로그래밍", 1L, LocalDate.of(2024, 5, 2), LocalDate.of(2024, 5, 1), SessionType.PAID, 10000, 100); }).withMessageMatching("강의 종료일보다 강의 시작일이 늦을 수 없습니다."); } + + @DisplayName("유료 강의는 강의 최대 수강 인원을 초과할 수 없다") + @Test + void paidLectureCannotOverMaximumAttendees() { + // given & when & then + assertThatExceptionOfType(IllegalArgumentException.class) + .isThrownBy(() -> { + new Session(1L, "객체지향 프로그래밍", 1L, LocalDate.of(2024, 5, 2), LocalDate.of(2024, 5, 6), SessionType.PAID, 100, 101); + }).withMessageMatching("유료 강의는 강의 최대 수강 인원을 초과할 수 없다."); + + } + + @DisplayName("무료 강의는 최대 수강 인원 제한이 없다") + @Test + void freeLectureCannotOverMaximumAttendees() { + // given&when + Session freeSession = new Session(1L, "객체지향 프로그래밍", 1L, LocalDate.of(2024, 5, 2), LocalDate.of(2024, 5, 6), SessionType.FREE, 100, 101); + + // then + assertThat(freeSession).isNotNull(); + } } From 99445e9cdea776e4b10de008e2f5c20154316116 Mon Sep 17 00:00:00 2001 From: Sangmin Date: Thu, 18 Apr 2024 20:10:54 +0900 Subject: [PATCH 11/24] =?UTF-8?q?feat:=20'=EC=9C=A0=EB=A3=8C=20=EA=B0=95?= =?UTF-8?q?=EC=9D=98=EB=8A=94=20=EC=88=98=EA=B0=95=EC=83=9D=EC=9D=B4=20?= =?UTF-8?q?=EA=B2=B0=EC=A0=9C=ED=95=9C=20=EA=B8=88=EC=95=A1=EA=B3=BC=20?= =?UTF-8?q?=EC=88=98=EA=B0=95=EB=A3=8C=EA=B0=80=20=EC=9D=BC=EC=B9=98?= =?UTF-8?q?=ED=95=A0=20=EB=95=8C=20=EC=88=98=EA=B0=95=20=EC=8B=A0=EC=B2=AD?= =?UTF-8?q?=EC=9D=B4=20=EA=B0=80=EB=8A=A5'=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= =?UTF-8?q?=20=EC=84=B1=EA=B3=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- TODO.md | 4 +- .../nextstep/payments/domain/Payment.java | 4 + .../nextstep/sessions/domain/Session.java | 16 +- .../nextstep/sessions/domain/Sessions.java | 4 + .../java/nextstep/users/domain/NsUser.java | 259 ++++++++++-------- .../nextstep/courses/domain/CourseTest.java | 4 +- .../nextstep/sessions/domain/SessionTest.java | 16 +- .../nextstep/users/domain/NsUserTest.java | 24 ++ 8 files changed, 204 insertions(+), 127 deletions(-) diff --git a/TODO.md b/TODO.md index 74adabd2d..a10c72315 100644 --- a/TODO.md +++ b/TODO.md @@ -8,10 +8,10 @@ - [x] 이미지 크기는 1MB 이하여야 한다. - [x] 이미지 타입은 gif, jpg(jpeg 포함), png, svg만 허용한다. - [x] 이미지의 width는 300픽셀, height는 200픽셀 이상이어야 하며, width와 height의 비율은 3:2여야 한다. -- [ ] 강의는 무료 강의와 유료 강의로 나뉜다. +- [x] 강의는 무료 강의와 유료 강의로 나뉜다. - [x] 무료 강의는 최대 수강 인원 제한이 없다. - [x] 유료 강의는 강의 최대 수강 인원을 초과할 수 없다. - - [ ] 유료 강의는 수강생이 결제한 금액과 수강료가 일치할 때 수강 신청이 가능하다. + - [x] 유료 강의는 수강생이 결제한 금액과 수강료가 일치할 때 수강 신청이 가능하다. - [ ] 강의 상태는 준비중, 모집중, 종료 3가지 상태를 가진다. - [ ] 강의 수강신청은 강의 상태가 모집중일 때만 가능하다. - [ ] 유료 강의의 경우 결제는 이미 완료한 것으로 가정하고 이후 과정을 구현한다. diff --git a/src/main/java/nextstep/payments/domain/Payment.java b/src/main/java/nextstep/payments/domain/Payment.java index 57d833f85..443899865 100644 --- a/src/main/java/nextstep/payments/domain/Payment.java +++ b/src/main/java/nextstep/payments/domain/Payment.java @@ -26,4 +26,8 @@ public Payment(String id, Long sessionId, Long nsUserId, Long amount) { this.amount = amount; this.createdAt = LocalDateTime.now(); } + + public Long getAmount() { + return amount; + } } diff --git a/src/main/java/nextstep/sessions/domain/Session.java b/src/main/java/nextstep/sessions/domain/Session.java index 99ed6b767..1c8127f93 100644 --- a/src/main/java/nextstep/sessions/domain/Session.java +++ b/src/main/java/nextstep/sessions/domain/Session.java @@ -15,8 +15,9 @@ public class Session { private SessionType sessionType; private Integer maximumAttendeeNumber; private Integer attendeeNumber; + private Integer TuitionFee; - public Session(final long id, final String title, final long courseId, final LocalDate startedAt, final LocalDate endedAt, final SessionType sessionType, final int maximumAttendeeNumber, final int attendeeNumber) { + public Session(final long id, final String title, final long courseId, final LocalDate startedAt, final LocalDate endedAt, final SessionType sessionType, final int maximumAttendeeNumber, final int attendeeNumber, final int TuitionFee) { validateSessionDate(startedAt, endedAt); validateSessionMaximumAttendeeNumber(sessionType, maximumAttendeeNumber, attendeeNumber); this.id = id; @@ -27,6 +28,7 @@ public Session(final long id, final String title, final long courseId, final Loc this.sessionType = sessionType; this.maximumAttendeeNumber = maximumAttendeeNumber; this.attendeeNumber = attendeeNumber; + this.TuitionFee = TuitionFee; } private void validateSessionMaximumAttendeeNumber(final SessionType sessionType, final int maximumAttendeeNumber, final int attendeeNumber) { @@ -40,4 +42,16 @@ private static void validateSessionDate(final LocalDate startedAt, final LocalDa throw new IllegalArgumentException("강의 종료일보다 강의 시작일이 늦을 수 없습니다."); } } + + public boolean isPaidSession() { + return sessionType.equals(SessionType.PAID); + } + + public Integer getTuitionFee() { + return TuitionFee; + } + + public Long getId() { + return id; + } } diff --git a/src/main/java/nextstep/sessions/domain/Sessions.java b/src/main/java/nextstep/sessions/domain/Sessions.java index a6046693f..2fab3f806 100644 --- a/src/main/java/nextstep/sessions/domain/Sessions.java +++ b/src/main/java/nextstep/sessions/domain/Sessions.java @@ -12,4 +12,8 @@ public Sessions(List sessions) { public int size() { return sessions.size(); } + + public void add(final Session session) { + sessions.add(session); + } } diff --git a/src/main/java/nextstep/users/domain/NsUser.java b/src/main/java/nextstep/users/domain/NsUser.java index 62ec5138c..b607924f6 100755 --- a/src/main/java/nextstep/users/domain/NsUser.java +++ b/src/main/java/nextstep/users/domain/NsUser.java @@ -1,138 +1,159 @@ package nextstep.users.domain; import nextstep.qna.UnAuthorizedException; +import nextstep.sessions.domain.Session; +import nextstep.sessions.domain.Sessions; import java.time.LocalDateTime; +import java.util.ArrayList; import java.util.Objects; public class NsUser { - public static final GuestNsUser GUEST_USER = new GuestNsUser(); + public static final GuestNsUser GUEST_USER = new GuestNsUser(); - private Long id; + private Long id; - private String userId; + private String userId; - private String password; + private String password; - private String name; + private String name; - private String email; + private String email; - private LocalDateTime createdAt; + private Sessions sessions; - private LocalDateTime updatedAt; + private LocalDateTime createdAt; - public NsUser() { - } + private LocalDateTime updatedAt; - public NsUser(Long id, String userId, String password, String name, String email) { - this(id, userId, password, name, email, LocalDateTime.now(), null); - } + public NsUser() { + } - public NsUser(Long id, String userId, String password, String name, String email, LocalDateTime createdAt, LocalDateTime updatedAt) { - this.id = id; - this.userId = userId; - this.password = password; - this.name = name; - this.email = email; - this.createdAt = createdAt; - this.updatedAt = updatedAt; - } - - public Long getId() { - return id; - } - - public String getUserId() { - return userId; - } - - public NsUser setUserId(String userId) { - this.userId = userId; - return this; - } - - public String getPassword() { - return password; - } - - public NsUser setPassword(String password) { - this.password = password; - return this; - } - - public String getName() { - return name; - } - - public NsUser setName(String name) { - this.name = name; - return this; - } - - public String getEmail() { - return email; - } - - public NsUser setEmail(String email) { - this.email = email; - return this; - } - - public void update(NsUser loginUser, NsUser target) { - if (!matchUserId(loginUser.getUserId())) { - throw new UnAuthorizedException(); - } - - if (!matchPassword(target.getPassword())) { - throw new UnAuthorizedException(); - } - - this.name = target.name; - this.email = target.email; - } - - public boolean matchUser(NsUser target) { - return matchUserId(target.getUserId()); - } - - private boolean matchUserId(String userId) { - return this.userId.equals(userId); - } - - public boolean matchPassword(String targetPassword) { - return password.equals(targetPassword); - } - - public boolean equalsNameAndEmail(NsUser target) { - if (Objects.isNull(target)) { - return false; - } - - return name.equals(target.name) && - email.equals(target.email); - } - - public boolean isGuestUser() { - return false; - } - - private static class GuestNsUser extends NsUser { - @Override - public boolean isGuestUser() { - return true; - } - } - - @Override - public String toString() { - return "NsUser{" + - "id=" + id + - ", userId='" + userId + '\'' + - ", name='" + name + '\'' + - ", email='" + email + '\'' + - ", createdAt=" + createdAt + - ", updatedAt=" + updatedAt + - '}'; - } + public NsUser(Long id, String userId, String password, String name, String email) { + this(id, userId, password, name, email, LocalDateTime.now(), null); + } + + public NsUser(Long id, String userId, String password, String name, String email, LocalDateTime createdAt, LocalDateTime updatedAt) { + this.id = id; + this.userId = userId; + this.password = password; + this.name = name; + this.email = email; + this.createdAt = createdAt; + this.updatedAt = updatedAt; + this.sessions = new Sessions(new ArrayList<>()); + } + + public Long getId() { + return id; + } + + public String getUserId() { + return userId; + } + + public NsUser setUserId(String userId) { + this.userId = userId; + return this; + } + + public String getPassword() { + return password; + } + + public NsUser setPassword(String password) { + this.password = password; + return this; + } + + public String getName() { + return name; + } + + public NsUser setName(String name) { + this.name = name; + return this; + } + + public String getEmail() { + return email; + } + + public NsUser setEmail(String email) { + this.email = email; + return this; + } + + public void update(NsUser loginUser, NsUser target) { + if (!matchUserId(loginUser.getUserId())) { + throw new UnAuthorizedException(); + } + + if (!matchPassword(target.getPassword())) { + throw new UnAuthorizedException(); + } + + this.name = target.name; + this.email = target.email; + } + + public boolean matchUser(NsUser target) { + return matchUserId(target.getUserId()); + } + + private boolean matchUserId(String userId) { + return this.userId.equals(userId); + } + + public boolean matchPassword(String targetPassword) { + return password.equals(targetPassword); + } + + public boolean equalsNameAndEmail(NsUser target) { + if (Objects.isNull(target)) { + return false; + } + + return name.equals(target.name) && + email.equals(target.email); + } + + public boolean isGuestUser() { + return false; + } + + public void registerSession(final Session session, final long paymentAmount) { + if (session.isPaidSession() && session.getTuitionFee() != paymentAmount) { + throw new IllegalArgumentException("수강료가 일치하지 않습니다."); + } + addSession(session); + } + + private void addSession(final Session session) { + sessions.add(session); + } + + public Sessions getSessions() { + return sessions; + } + + private static class GuestNsUser extends NsUser { + @Override + public boolean isGuestUser() { + return true; + } + } + + @Override + public String toString() { + return "NsUser{" + + "id=" + id + + ", userId='" + userId + '\'' + + ", name='" + name + '\'' + + ", email='" + email + '\'' + + ", createdAt=" + createdAt + + ", updatedAt=" + updatedAt + + '}'; + } } diff --git a/src/test/java/nextstep/courses/domain/CourseTest.java b/src/test/java/nextstep/courses/domain/CourseTest.java index 63d570bb5..b8831669d 100644 --- a/src/test/java/nextstep/courses/domain/CourseTest.java +++ b/src/test/java/nextstep/courses/domain/CourseTest.java @@ -27,8 +27,8 @@ void createCourseWithCardinality() { void CreateCourseWithMultipleSessions() { // given & when - List sessionList = List.of(new Session(1L, "객체지향 프로그래밍", 1L, LocalDate.of(2024, 5, 2), LocalDate.of(2024, 5, 30), SessionType.PAID, 10000, 100), - new Session(2L, "클래스 디자인", 1L, LocalDate.of(2024, 6, 2), LocalDate.of(2024, 2, 20), SessionType.PAID, 10000, 100)); + List sessionList = List.of(new Session(1L, "객체지향 프로그래밍", 1L, LocalDate.of(2024, 5, 2), LocalDate.of(2024, 5, 30), SessionType.PAID, 10000, 100, 10000), + new Session(2L, "클래스 디자인", 1L, LocalDate.of(2024, 6, 2), LocalDate.of(2024, 2, 20), SessionType.PAID, 10000, 100, 10000)); Sessions sessions = new Sessions(sessionList); Course course = new Course(1L, "tdd 클린코드", 1L, sessions); diff --git a/src/test/java/nextstep/sessions/domain/SessionTest.java b/src/test/java/nextstep/sessions/domain/SessionTest.java index d68a37dfb..2e406b0b3 100644 --- a/src/test/java/nextstep/sessions/domain/SessionTest.java +++ b/src/test/java/nextstep/sessions/domain/SessionTest.java @@ -15,7 +15,7 @@ void notCourseEndDateEarlierThanStartDate() { // given & when & then assertThatExceptionOfType(IllegalArgumentException.class) .isThrownBy(() -> { - new Session(1L, "객체지향 프로그래밍", 1L, LocalDate.of(2024, 5, 2), LocalDate.of(2024, 5, 1), SessionType.PAID, 10000, 100); + new Session(1L, "객체지향 프로그래밍", 1L, LocalDate.of(2024, 5, 2), LocalDate.of(2024, 5, 1), SessionType.PAID, 10000, 100, 10000); }).withMessageMatching("강의 종료일보다 강의 시작일이 늦을 수 없습니다."); } @@ -25,7 +25,7 @@ void paidLectureCannotOverMaximumAttendees() { // given & when & then assertThatExceptionOfType(IllegalArgumentException.class) .isThrownBy(() -> { - new Session(1L, "객체지향 프로그래밍", 1L, LocalDate.of(2024, 5, 2), LocalDate.of(2024, 5, 6), SessionType.PAID, 100, 101); + new Session(1L, "객체지향 프로그래밍", 1L, LocalDate.of(2024, 5, 2), LocalDate.of(2024, 5, 6), SessionType.PAID, 100, 101, 10000); }).withMessageMatching("유료 강의는 강의 최대 수강 인원을 초과할 수 없다."); } @@ -34,9 +34,19 @@ void paidLectureCannotOverMaximumAttendees() { @Test void freeLectureCannotOverMaximumAttendees() { // given&when - Session freeSession = new Session(1L, "객체지향 프로그래밍", 1L, LocalDate.of(2024, 5, 2), LocalDate.of(2024, 5, 6), SessionType.FREE, 100, 101); + Session freeSession = new Session(1L, "객체지향 프로그래밍", 1L, LocalDate.of(2024, 5, 2), LocalDate.of(2024, 5, 6), SessionType.FREE, 100, 101, 10000); // then assertThat(freeSession).isNotNull(); } + + @DisplayName("유료 강의는 수강생이 결제한 금액과 수강료가 일치할 때 수강 신청이 가능하다") + @Test + void paidLectureCanBeAppliedIfPaidAmountEqualsTuitionFee() { + // given + + // when + + // then + } } diff --git a/src/test/java/nextstep/users/domain/NsUserTest.java b/src/test/java/nextstep/users/domain/NsUserTest.java index ffac9f9a7..0f2c08994 100644 --- a/src/test/java/nextstep/users/domain/NsUserTest.java +++ b/src/test/java/nextstep/users/domain/NsUserTest.java @@ -1,6 +1,30 @@ package nextstep.users.domain; +import nextstep.payments.domain.Payment; +import nextstep.sessions.domain.Session; +import nextstep.sessions.domain.SessionType; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.time.LocalDate; + +import static org.assertj.core.api.Assertions.assertThat; + public class NsUserTest { public static final NsUser JAVAJIGI = new NsUser(1L, "javajigi", "password", "name", "javajigi@slipp.net"); public static final NsUser SANJIGI = new NsUser(2L, "sanjigi", "password", "name", "sanjigi@slipp.net"); + + @DisplayName("유료 강의는 수강생이 결제한 금액과 수강료가 일치할 때 수강 신청이 가능하다") + @Test + void paidLectureCanBeAppliedIfPaidAmountEqualsTuitionFee() { + // given + Session paidLecture = new Session(1L, "객체지향 프로그래밍", 1L, LocalDate.of(2024, 5, 2), LocalDate.of(2024, 5, 6), SessionType.PAID, 100, 100, 10000); + Payment payment = new Payment("1", paidLecture.getId(), JAVAJIGI.getId(), 10000L); + + // when + SANJIGI.registerSession(paidLecture, payment.getAmount()); + + // then + assertThat(SANJIGI.getSessions().size()).isEqualTo(1); + } } From 6b42b1ee752789bc0566ad82d235b452ced51652 Mon Sep 17 00:00:00 2001 From: Sangmin Date: Fri, 19 Apr 2024 16:44:49 +0900 Subject: [PATCH 12/24] =?UTF-8?q?feat:=20'=EA=B0=95=EC=9D=98=20=EC=88=98?= =?UTF-8?q?=EA=B0=95=EC=8B=A0=EC=B2=AD=EC=9D=80=20=EA=B0=95=EC=9D=98=20?= =?UTF-8?q?=EC=83=81=ED=83=9C=EA=B0=80=20=EB=AA=A8=EC=A7=91=EC=A4=91?= =?UTF-8?q?=EC=9D=BC=20=EB=95=8C=EB=A7=8C=20=EA=B0=80=EB=8A=A5'=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=84=B1=EA=B3=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- TODO.md | 4 ++-- .../nextstep/sessions/domain/Session.java | 12 ++++++++++++ .../sessions/domain/SessionStatus.java | 13 +++++++++++++ .../java/nextstep/users/domain/NsUser.java | 1 + .../nextstep/users/domain/NsUserTest.java | 19 +++++++++++++++++++ 5 files changed, 47 insertions(+), 2 deletions(-) create mode 100644 src/main/java/nextstep/sessions/domain/SessionStatus.java diff --git a/TODO.md b/TODO.md index a10c72315..446ba94ec 100644 --- a/TODO.md +++ b/TODO.md @@ -12,7 +12,7 @@ - [x] 무료 강의는 최대 수강 인원 제한이 없다. - [x] 유료 강의는 강의 최대 수강 인원을 초과할 수 없다. - [x] 유료 강의는 수강생이 결제한 금액과 수강료가 일치할 때 수강 신청이 가능하다. -- [ ] 강의 상태는 준비중, 모집중, 종료 3가지 상태를 가진다. -- [ ] 강의 수강신청은 강의 상태가 모집중일 때만 가능하다. +- [x] 강의 상태는 준비중, 모집중, 종료 3가지 상태를 가진다. +- [x] 강의 수강신청은 강의 상태가 모집중일 때만 가능하다. - [ ] 유료 강의의 경우 결제는 이미 완료한 것으로 가정하고 이후 과정을 구현한다. - [ ] 결제를 완료한 결제 정보는 payments 모듈을 통해 관리되며, 결제 정보는 Payment 객체에 담겨 반한된다. \ No newline at end of file diff --git a/src/main/java/nextstep/sessions/domain/Session.java b/src/main/java/nextstep/sessions/domain/Session.java index 1c8127f93..ef3c8011d 100644 --- a/src/main/java/nextstep/sessions/domain/Session.java +++ b/src/main/java/nextstep/sessions/domain/Session.java @@ -16,6 +16,7 @@ public class Session { private Integer maximumAttendeeNumber; private Integer attendeeNumber; private Integer TuitionFee; + private SessionStatus sessionStatus; public Session(final long id, final String title, final long courseId, final LocalDate startedAt, final LocalDate endedAt, final SessionType sessionType, final int maximumAttendeeNumber, final int attendeeNumber, final int TuitionFee) { validateSessionDate(startedAt, endedAt); @@ -29,6 +30,7 @@ public Session(final long id, final String title, final long courseId, final Loc this.maximumAttendeeNumber = maximumAttendeeNumber; this.attendeeNumber = attendeeNumber; this.TuitionFee = TuitionFee; + this.sessionStatus = SessionStatus.READY; } private void validateSessionMaximumAttendeeNumber(final SessionType sessionType, final int maximumAttendeeNumber, final int attendeeNumber) { @@ -54,4 +56,14 @@ public Integer getTuitionFee() { public Long getId() { return id; } + + public void changeSessionStatus(final SessionStatus sessionStatus) { + this.sessionStatus = sessionStatus; + } + + public void validateOpeningSession() { + if (!sessionStatus.equals(SessionStatus.OPENED)) { + throw new IllegalArgumentException("강의 모집 상태가 아닙니다. 수강 신청이 불가능합니다."); + } + } } diff --git a/src/main/java/nextstep/sessions/domain/SessionStatus.java b/src/main/java/nextstep/sessions/domain/SessionStatus.java new file mode 100644 index 000000000..06c35d726 --- /dev/null +++ b/src/main/java/nextstep/sessions/domain/SessionStatus.java @@ -0,0 +1,13 @@ +package nextstep.sessions.domain; + +public enum SessionStatus { + READY("준비중"), + OPENED("모집중"), + CLOSED("종료"); + + private final String description; + + SessionStatus(String description) { + this.description = description; + } +} diff --git a/src/main/java/nextstep/users/domain/NsUser.java b/src/main/java/nextstep/users/domain/NsUser.java index b607924f6..9e7ae8d89 100755 --- a/src/main/java/nextstep/users/domain/NsUser.java +++ b/src/main/java/nextstep/users/domain/NsUser.java @@ -131,6 +131,7 @@ public void registerSession(final Session session, final long paymentAmount) { } private void addSession(final Session session) { + session.validateOpeningSession(); sessions.add(session); } diff --git a/src/test/java/nextstep/users/domain/NsUserTest.java b/src/test/java/nextstep/users/domain/NsUserTest.java index 0f2c08994..8665ebbeb 100644 --- a/src/test/java/nextstep/users/domain/NsUserTest.java +++ b/src/test/java/nextstep/users/domain/NsUserTest.java @@ -2,6 +2,7 @@ import nextstep.payments.domain.Payment; import nextstep.sessions.domain.Session; +import nextstep.sessions.domain.SessionStatus; import nextstep.sessions.domain.SessionType; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -9,6 +10,7 @@ import java.time.LocalDate; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.AssertionsForClassTypes.assertThatExceptionOfType; public class NsUserTest { public static final NsUser JAVAJIGI = new NsUser(1L, "javajigi", "password", "name", "javajigi@slipp.net"); @@ -27,4 +29,21 @@ void paidLectureCanBeAppliedIfPaidAmountEqualsTuitionFee() { // then assertThat(SANJIGI.getSessions().size()).isEqualTo(1); } + + @DisplayName("강의 수강신청은 강의 상태가 모집중일 때만 가능하다") + @Test + void CourseRegistrationIsPossibleWhenCourseStatusIsOpening() { + // given + Session paidLecture = new Session(1L, "객체지향 프로그래밍", 1L, LocalDate.of(2024, 5, 2), LocalDate.of(2024, 5, 6), SessionType.PAID, 100, 100, 10000); + Payment payment = new Payment("1", paidLecture.getId(), JAVAJIGI.getId(), 10000L); + paidLecture.changeSessionStatus(SessionStatus.CLOSED); + + // when&then + assertThatExceptionOfType(IllegalArgumentException.class) + .isThrownBy(() -> { + SANJIGI.registerSession(paidLecture, payment.getAmount()); + }).withMessageMatching("강의 모집 상태가 아닙니다. 수강 신청이 불가능합니다."); + + + } } From 0896fa91d1e80da2b870273e97c45d32bbcee581 Mon Sep 17 00:00:00 2001 From: Sangmin Date: Fri, 19 Apr 2024 17:00:14 +0900 Subject: [PATCH 13/24] =?UTF-8?q?refactor:=20=EC=82=AC=EC=9A=A9=EC=95=88?= =?UTF-8?q?=ED=95=98=EB=8A=94=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/nextstep/sessions/domain/SessionTest.java | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/test/java/nextstep/sessions/domain/SessionTest.java b/src/test/java/nextstep/sessions/domain/SessionTest.java index 2e406b0b3..7b30d5671 100644 --- a/src/test/java/nextstep/sessions/domain/SessionTest.java +++ b/src/test/java/nextstep/sessions/domain/SessionTest.java @@ -39,14 +39,4 @@ void freeLectureCannotOverMaximumAttendees() { // then assertThat(freeSession).isNotNull(); } - - @DisplayName("유료 강의는 수강생이 결제한 금액과 수강료가 일치할 때 수강 신청이 가능하다") - @Test - void paidLectureCanBeAppliedIfPaidAmountEqualsTuitionFee() { - // given - - // when - - // then - } } From 25a693162683aefcc7edeef0474e23dd8bffa58e Mon Sep 17 00:00:00 2001 From: Sangmin Date: Sun, 21 Apr 2024 16:07:18 +0900 Subject: [PATCH 14/24] =?UTF-8?q?refactor:=20imageWidth,=20imageHeight=20?= =?UTF-8?q?=ED=95=84=EB=93=9C=EB=AA=85=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/nextstep/image/domain/ImageShape.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/main/java/nextstep/image/domain/ImageShape.java b/src/main/java/nextstep/image/domain/ImageShape.java index 3c1f0bbd4..213dbde60 100644 --- a/src/main/java/nextstep/image/domain/ImageShape.java +++ b/src/main/java/nextstep/image/domain/ImageShape.java @@ -1,17 +1,17 @@ package nextstep.image.domain; public class ImageShape { - private ImageWidth imageWidth; - private ImageHeight imageHeight; + private ImageWidth width; + private ImageHeight height; - public ImageShape(ImageWidth imageWidth, ImageHeight imageHeight) { - validateShape(imageWidth, imageHeight); - this.imageWidth = imageWidth; - this.imageHeight = imageHeight; + public ImageShape(ImageWidth width, ImageHeight height) { + validateShape(width, height); + this.width = width; + this.height = height; } - private static void validateShape(final ImageWidth imageWidth, final ImageHeight imageHeight) { - if (imageWidth.getWidth() * 2 != imageHeight.getHeight() * 3) { + private static void validateShape(final ImageWidth width, final ImageHeight height) { + if (width.getWidth() * 2 != height.getHeight() * 3) { throw new IllegalArgumentException("가로 세로 비율은 3:2이어야 합니다."); } } From 8ca928bbaf1fc7b7ed0c3ccbaac0e921f2af9039 Mon Sep 17 00:00:00 2001 From: Sangmin Date: Sun, 21 Apr 2024 19:13:30 +0900 Subject: [PATCH 15/24] =?UTF-8?q?refactor:=20EndedAt,=20StartedAt=20?= =?UTF-8?q?=EB=9E=98=ED=95=91=ED=81=B4=EB=9E=98=EC=8A=A4=EB=A1=9C=20?= =?UTF-8?q?=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../nextstep/sessions/domain/EndedAt.java | 16 +++++++++++ .../nextstep/sessions/domain/Session.java | 28 ++++++++----------- .../nextstep/sessions/domain/SessionDate.java | 21 ++++++++++++++ .../nextstep/sessions/domain/StartedAt.java | 16 +++++++++++ 4 files changed, 65 insertions(+), 16 deletions(-) create mode 100644 src/main/java/nextstep/sessions/domain/EndedAt.java create mode 100644 src/main/java/nextstep/sessions/domain/SessionDate.java create mode 100644 src/main/java/nextstep/sessions/domain/StartedAt.java diff --git a/src/main/java/nextstep/sessions/domain/EndedAt.java b/src/main/java/nextstep/sessions/domain/EndedAt.java new file mode 100644 index 000000000..56e4c64c0 --- /dev/null +++ b/src/main/java/nextstep/sessions/domain/EndedAt.java @@ -0,0 +1,16 @@ +package nextstep.sessions.domain; + +import java.time.LocalDate; + +public class EndedAt { + + private final LocalDate endedAt; + + public EndedAt(LocalDate endedAt) { + this.endedAt = endedAt; + } + + public LocalDate getEndedAt() { + return endedAt; + } +} diff --git a/src/main/java/nextstep/sessions/domain/Session.java b/src/main/java/nextstep/sessions/domain/Session.java index ef3c8011d..b61878916 100644 --- a/src/main/java/nextstep/sessions/domain/Session.java +++ b/src/main/java/nextstep/sessions/domain/Session.java @@ -9,28 +9,30 @@ public class Session { private Long id; private String title; private Long courseId; - private LocalDate startedAt; - private LocalDate endedAt; + private SessionDate sessionDate; private Image image; private SessionType sessionType; private Integer maximumAttendeeNumber; private Integer attendeeNumber; - private Integer TuitionFee; + private Integer tuitionFee; private SessionStatus sessionStatus; - public Session(final long id, final String title, final long courseId, final LocalDate startedAt, final LocalDate endedAt, final SessionType sessionType, final int maximumAttendeeNumber, final int attendeeNumber, final int TuitionFee) { - validateSessionDate(startedAt, endedAt); + public Session(final Long id, final String title, final Long courseId, final LocalDate startedAt, final LocalDate endedAt, final SessionType sessionType, final Integer maximumAttendeeNumber, final Integer attendeeNumber, final Integer tuitionFee) { + this(id, title, courseId, new SessionDate(new StartedAt(startedAt), new EndedAt(endedAt)), null, sessionType, maximumAttendeeNumber, attendeeNumber, tuitionFee, SessionStatus.READY); + } + + public Session(final Long id, final String title, final Long courseId, final SessionDate sessionDate, final Image image, final SessionType sessionType, final Integer maximumAttendeeNumber, final Integer attendeeNumber, final Integer tuitionFee, final SessionStatus sessionStatus) { validateSessionMaximumAttendeeNumber(sessionType, maximumAttendeeNumber, attendeeNumber); this.id = id; this.title = title; this.courseId = courseId; - this.startedAt = startedAt; - this.endedAt = endedAt; + this.sessionDate = sessionDate; + this.image = image; this.sessionType = sessionType; this.maximumAttendeeNumber = maximumAttendeeNumber; this.attendeeNumber = attendeeNumber; - this.TuitionFee = TuitionFee; - this.sessionStatus = SessionStatus.READY; + this.tuitionFee = tuitionFee; + this.sessionStatus = sessionStatus; } private void validateSessionMaximumAttendeeNumber(final SessionType sessionType, final int maximumAttendeeNumber, final int attendeeNumber) { @@ -39,18 +41,12 @@ private void validateSessionMaximumAttendeeNumber(final SessionType sessionType, } } - private static void validateSessionDate(final LocalDate startedAt, final LocalDate endedAt) { - if (startedAt.isAfter(endedAt)) { - throw new IllegalArgumentException("강의 종료일보다 강의 시작일이 늦을 수 없습니다."); - } - } - public boolean isPaidSession() { return sessionType.equals(SessionType.PAID); } public Integer getTuitionFee() { - return TuitionFee; + return tuitionFee; } public Long getId() { diff --git a/src/main/java/nextstep/sessions/domain/SessionDate.java b/src/main/java/nextstep/sessions/domain/SessionDate.java new file mode 100644 index 000000000..124d8504e --- /dev/null +++ b/src/main/java/nextstep/sessions/domain/SessionDate.java @@ -0,0 +1,21 @@ +package nextstep.sessions.domain; + +import java.time.LocalDate; + +public class SessionDate { + + private final StartedAt startedAt; + private final EndedAt endedAt; + + public SessionDate(StartedAt startedAt, EndedAt endedAt) { + validateSessionDate(startedAt.getStartedAt(), endedAt.getEndedAt()); + this.startedAt = startedAt; + this.endedAt = endedAt; + } + + private static void validateSessionDate(final LocalDate startedAt, final LocalDate endedAt) { + if (startedAt.isAfter(endedAt)) { + throw new IllegalArgumentException("강의 종료일보다 강의 시작일이 늦을 수 없습니다."); + } + } +} diff --git a/src/main/java/nextstep/sessions/domain/StartedAt.java b/src/main/java/nextstep/sessions/domain/StartedAt.java new file mode 100644 index 000000000..caaef7d2d --- /dev/null +++ b/src/main/java/nextstep/sessions/domain/StartedAt.java @@ -0,0 +1,16 @@ +package nextstep.sessions.domain; + +import java.time.LocalDate; + +public class StartedAt { + + private final LocalDate startedAt; + + public StartedAt(LocalDate startedAt) { + this.startedAt = startedAt; + } + + public LocalDate getStartedAt() { + return startedAt; + } +} From d62232c34fc9a2a392080277ad06da15031d4122 Mon Sep 17 00:00:00 2001 From: Sangmin Date: Sun, 21 Apr 2024 19:14:45 +0900 Subject: [PATCH 16/24] =?UTF-8?q?refactor:=20sessionType=20description=20?= =?UTF-8?q?=ED=95=84=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/nextstep/sessions/domain/SessionType.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/main/java/nextstep/sessions/domain/SessionType.java b/src/main/java/nextstep/sessions/domain/SessionType.java index 4b9b32b08..fdd088aff 100644 --- a/src/main/java/nextstep/sessions/domain/SessionType.java +++ b/src/main/java/nextstep/sessions/domain/SessionType.java @@ -1,5 +1,12 @@ package nextstep.sessions.domain; public enum SessionType { - FREE, PAID + FREE("무료강의"), + PAID("유료강의"); + + private final String description; + + SessionType(String description) { + this.description = description; + } } From 409d49c4edf3938fdb261ad582061bdb615c6cac Mon Sep 17 00:00:00 2001 From: Sangmin Date: Mon, 22 Apr 2024 00:14:10 +0900 Subject: [PATCH 17/24] =?UTF-8?q?refactor:=20Charge,Enrollment,SessionInfo?= =?UTF-8?q?=20=ED=81=B4=EB=9E=98=EC=8A=A4=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/nextstep/image/domain/Image.java | 4 +- .../java/nextstep/sessions/domain/Charge.java | 17 +++++ .../sessions/domain/ChargeStatus.java | 22 ++++++ .../nextstep/sessions/domain/Enrollment.java | 44 +++++++++++ .../nextstep/sessions/domain/Session.java | 75 +++++-------------- .../nextstep/sessions/domain/SessionInfo.java | 16 ++++ .../sessions/domain/SessionStatus.java | 4 + .../nextstep/sessions/domain/SessionType.java | 12 --- .../java/nextstep/users/domain/NsUser.java | 12 --- .../nextstep/courses/domain/ChargeTest.java | 24 ++++++ .../nextstep/courses/domain/CourseTest.java | 9 +-- .../courses/domain/EnrollmentTest.java | 45 +++++++++++ .../courses/domain/SessionFixture.java | 24 ++++++ .../nextstep/sessions/domain/SessionTest.java | 24 +----- .../nextstep/users/domain/NsUserTest.java | 33 +------- 15 files changed, 222 insertions(+), 143 deletions(-) create mode 100644 src/main/java/nextstep/sessions/domain/Charge.java create mode 100644 src/main/java/nextstep/sessions/domain/ChargeStatus.java create mode 100644 src/main/java/nextstep/sessions/domain/Enrollment.java create mode 100644 src/main/java/nextstep/sessions/domain/SessionInfo.java delete mode 100644 src/main/java/nextstep/sessions/domain/SessionType.java create mode 100644 src/test/java/nextstep/courses/domain/ChargeTest.java create mode 100644 src/test/java/nextstep/courses/domain/EnrollmentTest.java create mode 100644 src/test/java/nextstep/courses/domain/SessionFixture.java diff --git a/src/main/java/nextstep/image/domain/Image.java b/src/main/java/nextstep/image/domain/Image.java index cb9453066..cc75f4be4 100644 --- a/src/main/java/nextstep/image/domain/Image.java +++ b/src/main/java/nextstep/image/domain/Image.java @@ -1,13 +1,11 @@ package nextstep.image.domain; public class Image { - private Long id; private ImageType type; private ImageShape shape; private Integer size; - public Image(final Long id, final ImageType type, final ImageShape shape, final Integer size) { - this.id = id; + public Image(final ImageType type, final ImageShape shape, final Integer size) { this.type = type; this.shape = shape; this.size = size; diff --git a/src/main/java/nextstep/sessions/domain/Charge.java b/src/main/java/nextstep/sessions/domain/Charge.java new file mode 100644 index 000000000..e164c8b88 --- /dev/null +++ b/src/main/java/nextstep/sessions/domain/Charge.java @@ -0,0 +1,17 @@ +package nextstep.sessions.domain; + +public class Charge { + + private final ChargeStatus status; + private final int price; + + public Charge(ChargeStatus status) { + this(status, 0); + } + + public Charge(ChargeStatus status, int price) { + status.valid(price); + this.status = status; + this.price = price; + } +} diff --git a/src/main/java/nextstep/sessions/domain/ChargeStatus.java b/src/main/java/nextstep/sessions/domain/ChargeStatus.java new file mode 100644 index 000000000..7a8e15e1f --- /dev/null +++ b/src/main/java/nextstep/sessions/domain/ChargeStatus.java @@ -0,0 +1,22 @@ +package nextstep.sessions.domain; + +public enum ChargeStatus { + FREE("무료강의"), + PAID("유료강의"); + + private final String description; + + ChargeStatus(String description) { + this.description = description; + } + + public void valid(int price) { + if (isFree() && price > 0) { + throw new IllegalArgumentException("무료 강의의 가격은 0이어야 합니다."); + } + } + + private boolean isFree() { + return this == FREE; + } +} diff --git a/src/main/java/nextstep/sessions/domain/Enrollment.java b/src/main/java/nextstep/sessions/domain/Enrollment.java new file mode 100644 index 000000000..1d788b776 --- /dev/null +++ b/src/main/java/nextstep/sessions/domain/Enrollment.java @@ -0,0 +1,44 @@ +package nextstep.sessions.domain; + +import nextstep.users.domain.NsUser; + +import java.util.ArrayList; +import java.util.List; + +public class Enrollment { + + private final SessionStatus sessionStatus; + private final int capacity; + private final List students; + + public Enrollment(SessionStatus sessionStatus, int capacity) { + this(sessionStatus, capacity, new ArrayList<>()); + } + + public Enrollment(SessionStatus sessionStatus, int capacity, List students) { + if (capacity < students.size()) { + throw new IllegalArgumentException("최대 수용 인원인 " + capacity + "명을 초과할 수 없습니다."); + } + this.sessionStatus = sessionStatus; + this.capacity = capacity; + this.students = students; + } + + public void enroll(NsUser student) { + if (!sessionStatus.isOpened()) { + throw new IllegalArgumentException("수강신청 상태가 아니라 수강신청할 수 없습니다."); + } + if (isFullCapacity()) { + throw new IllegalArgumentException("최대 수용 인원인 " + capacity + "명을 초과할 수 없습니다."); + } + if (students.contains(student)) { + throw new IllegalArgumentException(student.getName() + "는 이미 수강 신청한 학생입니다."); + } + students.add(student); + } + + private boolean isFullCapacity() { + return students.size() == capacity; + } + +} diff --git a/src/main/java/nextstep/sessions/domain/Session.java b/src/main/java/nextstep/sessions/domain/Session.java index b61878916..ea1891a05 100644 --- a/src/main/java/nextstep/sessions/domain/Session.java +++ b/src/main/java/nextstep/sessions/domain/Session.java @@ -1,65 +1,28 @@ package nextstep.sessions.domain; -import nextstep.image.domain.Image; - import java.time.LocalDate; public class Session { - private Long id; - private String title; - private Long courseId; - private SessionDate sessionDate; - private Image image; - private SessionType sessionType; - private Integer maximumAttendeeNumber; - private Integer attendeeNumber; - private Integer tuitionFee; - private SessionStatus sessionStatus; - - public Session(final Long id, final String title, final Long courseId, final LocalDate startedAt, final LocalDate endedAt, final SessionType sessionType, final Integer maximumAttendeeNumber, final Integer attendeeNumber, final Integer tuitionFee) { - this(id, title, courseId, new SessionDate(new StartedAt(startedAt), new EndedAt(endedAt)), null, sessionType, maximumAttendeeNumber, attendeeNumber, tuitionFee, SessionStatus.READY); - } - - public Session(final Long id, final String title, final Long courseId, final SessionDate sessionDate, final Image image, final SessionType sessionType, final Integer maximumAttendeeNumber, final Integer attendeeNumber, final Integer tuitionFee, final SessionStatus sessionStatus) { - validateSessionMaximumAttendeeNumber(sessionType, maximumAttendeeNumber, attendeeNumber); - this.id = id; - this.title = title; - this.courseId = courseId; + private final SessionInfo sessionInfo; + private final Charge charge; + private final Enrollment enrollment; + private final SessionDate sessionDate; + + public Session(String title, Long creatorId, + ChargeStatus chargeStatus, int price, + int capacity, SessionStatus sessionStatus, + LocalDate startDate, LocalDate endDate) { + this(new SessionInfo(title, creatorId, null), + new Charge(chargeStatus, price), + new Enrollment(sessionStatus, capacity), + new SessionDate(new StartedAt(startDate), new EndedAt(endDate))); + } + + public Session(SessionInfo sessionInfo, Charge charge, Enrollment enrollment, SessionDate sessionDate) { + this.sessionInfo = sessionInfo; + this.charge = charge; + this.enrollment = enrollment; this.sessionDate = sessionDate; - this.image = image; - this.sessionType = sessionType; - this.maximumAttendeeNumber = maximumAttendeeNumber; - this.attendeeNumber = attendeeNumber; - this.tuitionFee = tuitionFee; - this.sessionStatus = sessionStatus; - } - - private void validateSessionMaximumAttendeeNumber(final SessionType sessionType, final int maximumAttendeeNumber, final int attendeeNumber) { - if (sessionType.equals(SessionType.PAID) && maximumAttendeeNumber < attendeeNumber) { - throw new IllegalArgumentException("유료 강의는 강의 최대 수강 인원을 초과할 수 없다."); - } - } - - public boolean isPaidSession() { - return sessionType.equals(SessionType.PAID); - } - - public Integer getTuitionFee() { - return tuitionFee; - } - - public Long getId() { - return id; - } - - public void changeSessionStatus(final SessionStatus sessionStatus) { - this.sessionStatus = sessionStatus; - } - - public void validateOpeningSession() { - if (!sessionStatus.equals(SessionStatus.OPENED)) { - throw new IllegalArgumentException("강의 모집 상태가 아닙니다. 수강 신청이 불가능합니다."); - } } } diff --git a/src/main/java/nextstep/sessions/domain/SessionInfo.java b/src/main/java/nextstep/sessions/domain/SessionInfo.java new file mode 100644 index 000000000..b649413c1 --- /dev/null +++ b/src/main/java/nextstep/sessions/domain/SessionInfo.java @@ -0,0 +1,16 @@ +package nextstep.sessions.domain; + +import nextstep.image.domain.Image; + +public class SessionInfo { + + private final String title; + private final Long creatorId; + private final Image image; + + public SessionInfo(String title, Long creatorId, Image image) { + this.title = title; + this.creatorId = creatorId; + this.image = image; + } +} diff --git a/src/main/java/nextstep/sessions/domain/SessionStatus.java b/src/main/java/nextstep/sessions/domain/SessionStatus.java index 06c35d726..4d477500a 100644 --- a/src/main/java/nextstep/sessions/domain/SessionStatus.java +++ b/src/main/java/nextstep/sessions/domain/SessionStatus.java @@ -10,4 +10,8 @@ public enum SessionStatus { SessionStatus(String description) { this.description = description; } + + public boolean isOpened() { + return this == OPENED; + } } diff --git a/src/main/java/nextstep/sessions/domain/SessionType.java b/src/main/java/nextstep/sessions/domain/SessionType.java deleted file mode 100644 index fdd088aff..000000000 --- a/src/main/java/nextstep/sessions/domain/SessionType.java +++ /dev/null @@ -1,12 +0,0 @@ -package nextstep.sessions.domain; - -public enum SessionType { - FREE("무료강의"), - PAID("유료강의"); - - private final String description; - - SessionType(String description) { - this.description = description; - } -} diff --git a/src/main/java/nextstep/users/domain/NsUser.java b/src/main/java/nextstep/users/domain/NsUser.java index 9e7ae8d89..b03810344 100755 --- a/src/main/java/nextstep/users/domain/NsUser.java +++ b/src/main/java/nextstep/users/domain/NsUser.java @@ -123,18 +123,6 @@ public boolean isGuestUser() { return false; } - public void registerSession(final Session session, final long paymentAmount) { - if (session.isPaidSession() && session.getTuitionFee() != paymentAmount) { - throw new IllegalArgumentException("수강료가 일치하지 않습니다."); - } - addSession(session); - } - - private void addSession(final Session session) { - session.validateOpeningSession(); - sessions.add(session); - } - public Sessions getSessions() { return sessions; } diff --git a/src/test/java/nextstep/courses/domain/ChargeTest.java b/src/test/java/nextstep/courses/domain/ChargeTest.java new file mode 100644 index 000000000..48eba4aec --- /dev/null +++ b/src/test/java/nextstep/courses/domain/ChargeTest.java @@ -0,0 +1,24 @@ +package nextstep.courses.domain; + +import nextstep.sessions.domain.Charge; +import nextstep.sessions.domain.ChargeStatus; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; +import static org.assertj.core.api.AssertionsForClassTypes.assertThatExceptionOfType; + +public class ChargeTest { + + @DisplayName("무료 강의의 가격은 0이어야 합니다") + @Test + void freeSessionChargeEqualsZero() { + assertThatIllegalArgumentException() + .isThrownBy(() -> new Charge(ChargeStatus.FREE, 100_000)); + + assertThatExceptionOfType(IllegalArgumentException.class) + .isThrownBy(() -> { + new Charge(ChargeStatus.FREE, 100_000); + }).withMessageMatching("무료 강의의 가격은 0이어야 합니다."); + } +} diff --git a/src/test/java/nextstep/courses/domain/CourseTest.java b/src/test/java/nextstep/courses/domain/CourseTest.java index b8831669d..03f008eb3 100644 --- a/src/test/java/nextstep/courses/domain/CourseTest.java +++ b/src/test/java/nextstep/courses/domain/CourseTest.java @@ -1,12 +1,9 @@ package nextstep.courses.domain; -import nextstep.sessions.domain.Session; -import nextstep.sessions.domain.SessionType; -import nextstep.sessions.domain.Sessions; +import nextstep.sessions.domain.*; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import java.time.LocalDate; import java.util.List; import static org.assertj.core.api.Assertions.assertThat; @@ -27,8 +24,8 @@ void createCourseWithCardinality() { void CreateCourseWithMultipleSessions() { // given & when - List sessionList = List.of(new Session(1L, "객체지향 프로그래밍", 1L, LocalDate.of(2024, 5, 2), LocalDate.of(2024, 5, 30), SessionType.PAID, 10000, 100, 10000), - new Session(2L, "클래스 디자인", 1L, LocalDate.of(2024, 6, 2), LocalDate.of(2024, 2, 20), SessionType.PAID, 10000, 100, 10000)); + List sessionList = List.of(SessionFixture.createSessionWithEnrollment(50, SessionStatus.OPENED), + SessionFixture.createSessionWithEnrollment(50, SessionStatus.OPENED)); Sessions sessions = new Sessions(sessionList); Course course = new Course(1L, "tdd 클린코드", 1L, sessions); diff --git a/src/test/java/nextstep/courses/domain/EnrollmentTest.java b/src/test/java/nextstep/courses/domain/EnrollmentTest.java new file mode 100644 index 000000000..90dda402e --- /dev/null +++ b/src/test/java/nextstep/courses/domain/EnrollmentTest.java @@ -0,0 +1,45 @@ +package nextstep.courses.domain; + +import nextstep.sessions.domain.Enrollment; +import nextstep.sessions.domain.SessionStatus; +import nextstep.users.domain.NsUserTest; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThatExceptionOfType; + +public class EnrollmentTest { + @DisplayName("유료 강의는 강의 최대 수강 인원을 초과할 수 없다") + @Test + void paidLectureCannotOverMaximumAttendees() { + // given & when & then + Enrollment enrollment = new Enrollment(SessionStatus.OPENED, 1); + assertThatExceptionOfType(IllegalArgumentException.class) + .isThrownBy(() -> { + enrollment.enroll(NsUserTest.JAVAJIGI); + enrollment.enroll(NsUserTest.SANJIGI); + }).withMessageMatching("최대 수용 인원인 1명을 초과할 수 없습니다."); + + } + + @DisplayName("수강신청 상태가 아닐 때는 수강신청이 되지 않는다.") + @Test + void notCreateEnrollmentWithNotSessionOpened() { + Enrollment enrollment = new Enrollment(SessionStatus.CLOSED, 10); + assertThatExceptionOfType(IllegalArgumentException.class) + .isThrownBy(() -> { + enrollment.enroll(NsUserTest.JAVAJIGI); + }).withMessageMatching("수강신청 상태가 아니라 수강신청할 수 없습니다."); + } + + @DisplayName("수강신청을 이미 한 학생은 수강신청이 되지 않는다.") + @Test + void notCreateEnrollmentWithDuplicateStudent() { + Enrollment enrollment = new Enrollment(SessionStatus.OPENED, 10); + assertThatExceptionOfType(IllegalArgumentException.class) + .isThrownBy(() -> { + enrollment.enroll(NsUserTest.JAVAJIGI); + enrollment.enroll(NsUserTest.JAVAJIGI); + }).withMessageMatching("name는 이미 수강 신청한 학생입니다."); + } +} diff --git a/src/test/java/nextstep/courses/domain/SessionFixture.java b/src/test/java/nextstep/courses/domain/SessionFixture.java new file mode 100644 index 000000000..f620e3241 --- /dev/null +++ b/src/test/java/nextstep/courses/domain/SessionFixture.java @@ -0,0 +1,24 @@ +package nextstep.courses.domain; + +import nextstep.sessions.domain.ChargeStatus; +import nextstep.sessions.domain.Session; +import nextstep.sessions.domain.SessionStatus; + +import java.time.LocalDate; + +public class SessionFixture { + public static Session createSessionWithEnrollment(int capacity, SessionStatus status) { + return new Session( + "TDD, 클린 코드 with Java 16기", 2L, + ChargeStatus.PAID, 800_000, + capacity, status, + LocalDate.now(), LocalDate.now().plusDays(30)); + } + public static Session createSessionWithSessionDate(LocalDate startDate, LocalDate endDate) { + return new Session( + "TDD, 클린 코드 with Java 16기", 2L, + ChargeStatus.PAID, 800_000, + 10, SessionStatus.OPENED, + startDate, endDate); + } +} diff --git a/src/test/java/nextstep/sessions/domain/SessionTest.java b/src/test/java/nextstep/sessions/domain/SessionTest.java index 7b30d5671..1f2f63605 100644 --- a/src/test/java/nextstep/sessions/domain/SessionTest.java +++ b/src/test/java/nextstep/sessions/domain/SessionTest.java @@ -5,6 +5,7 @@ import java.time.LocalDate; +import static nextstep.courses.domain.SessionFixture.*; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.AssertionsForClassTypes.assertThatExceptionOfType; @@ -15,28 +16,7 @@ void notCourseEndDateEarlierThanStartDate() { // given & when & then assertThatExceptionOfType(IllegalArgumentException.class) .isThrownBy(() -> { - new Session(1L, "객체지향 프로그래밍", 1L, LocalDate.of(2024, 5, 2), LocalDate.of(2024, 5, 1), SessionType.PAID, 10000, 100, 10000); + createSessionWithSessionDate(LocalDate.of(2024, 5, 6), LocalDate.of(2024, 5, 2)); }).withMessageMatching("강의 종료일보다 강의 시작일이 늦을 수 없습니다."); } - - @DisplayName("유료 강의는 강의 최대 수강 인원을 초과할 수 없다") - @Test - void paidLectureCannotOverMaximumAttendees() { - // given & when & then - assertThatExceptionOfType(IllegalArgumentException.class) - .isThrownBy(() -> { - new Session(1L, "객체지향 프로그래밍", 1L, LocalDate.of(2024, 5, 2), LocalDate.of(2024, 5, 6), SessionType.PAID, 100, 101, 10000); - }).withMessageMatching("유료 강의는 강의 최대 수강 인원을 초과할 수 없다."); - - } - - @DisplayName("무료 강의는 최대 수강 인원 제한이 없다") - @Test - void freeLectureCannotOverMaximumAttendees() { - // given&when - Session freeSession = new Session(1L, "객체지향 프로그래밍", 1L, LocalDate.of(2024, 5, 2), LocalDate.of(2024, 5, 6), SessionType.FREE, 100, 101, 10000); - - // then - assertThat(freeSession).isNotNull(); - } } diff --git a/src/test/java/nextstep/users/domain/NsUserTest.java b/src/test/java/nextstep/users/domain/NsUserTest.java index 8665ebbeb..e7d920eaa 100644 --- a/src/test/java/nextstep/users/domain/NsUserTest.java +++ b/src/test/java/nextstep/users/domain/NsUserTest.java @@ -3,7 +3,7 @@ import nextstep.payments.domain.Payment; import nextstep.sessions.domain.Session; import nextstep.sessions.domain.SessionStatus; -import nextstep.sessions.domain.SessionType; +import nextstep.sessions.domain.ChargeStatus; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -15,35 +15,4 @@ public class NsUserTest { public static final NsUser JAVAJIGI = new NsUser(1L, "javajigi", "password", "name", "javajigi@slipp.net"); public static final NsUser SANJIGI = new NsUser(2L, "sanjigi", "password", "name", "sanjigi@slipp.net"); - - @DisplayName("유료 강의는 수강생이 결제한 금액과 수강료가 일치할 때 수강 신청이 가능하다") - @Test - void paidLectureCanBeAppliedIfPaidAmountEqualsTuitionFee() { - // given - Session paidLecture = new Session(1L, "객체지향 프로그래밍", 1L, LocalDate.of(2024, 5, 2), LocalDate.of(2024, 5, 6), SessionType.PAID, 100, 100, 10000); - Payment payment = new Payment("1", paidLecture.getId(), JAVAJIGI.getId(), 10000L); - - // when - SANJIGI.registerSession(paidLecture, payment.getAmount()); - - // then - assertThat(SANJIGI.getSessions().size()).isEqualTo(1); - } - - @DisplayName("강의 수강신청은 강의 상태가 모집중일 때만 가능하다") - @Test - void CourseRegistrationIsPossibleWhenCourseStatusIsOpening() { - // given - Session paidLecture = new Session(1L, "객체지향 프로그래밍", 1L, LocalDate.of(2024, 5, 2), LocalDate.of(2024, 5, 6), SessionType.PAID, 100, 100, 10000); - Payment payment = new Payment("1", paidLecture.getId(), JAVAJIGI.getId(), 10000L); - paidLecture.changeSessionStatus(SessionStatus.CLOSED); - - // when&then - assertThatExceptionOfType(IllegalArgumentException.class) - .isThrownBy(() -> { - SANJIGI.registerSession(paidLecture, payment.getAmount()); - }).withMessageMatching("강의 모집 상태가 아닙니다. 수강 신청이 불가능합니다."); - - - } } From 785c218c35a00fa73daa253fc7b27434ef7a245f Mon Sep 17 00:00:00 2001 From: Sangmin Date: Mon, 22 Apr 2024 13:27:12 +0900 Subject: [PATCH 18/24] =?UTF-8?q?test:=20payment=20=EC=99=84=EB=A3=8C=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=84=B1=EA=B3=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- TODO.md | 4 +-- .../nextstep/payments/domain/Payments.java | 20 +++++++++++ .../sessions}/domain/SessionFixture.java | 2 +- .../nextstep/courses/domain/CourseTest.java | 1 + .../nextstep/payment/domain/PaymentTest.java | 35 +++++++++++++++++++ .../domain/ChargeTest.java | 4 +-- .../domain/EnrollmentTest.java | 4 +-- .../domain/ImageTest.java | 2 +- .../nextstep/sessions/domain/SessionTest.java | 2 +- 9 files changed, 63 insertions(+), 11 deletions(-) create mode 100644 src/main/java/nextstep/payments/domain/Payments.java rename src/test/java/{nextstep/courses => fixture/sessions}/domain/SessionFixture.java (96%) create mode 100644 src/test/java/nextstep/payment/domain/PaymentTest.java rename src/test/java/nextstep/{courses => sessions}/domain/ChargeTest.java (86%) rename src/test/java/nextstep/{courses => sessions}/domain/EnrollmentTest.java (93%) rename src/test/java/nextstep/{courses => sessions}/domain/ImageTest.java (98%) diff --git a/TODO.md b/TODO.md index 446ba94ec..0848c2e86 100644 --- a/TODO.md +++ b/TODO.md @@ -14,5 +14,5 @@ - [x] 유료 강의는 수강생이 결제한 금액과 수강료가 일치할 때 수강 신청이 가능하다. - [x] 강의 상태는 준비중, 모집중, 종료 3가지 상태를 가진다. - [x] 강의 수강신청은 강의 상태가 모집중일 때만 가능하다. -- [ ] 유료 강의의 경우 결제는 이미 완료한 것으로 가정하고 이후 과정을 구현한다. -- [ ] 결제를 완료한 결제 정보는 payments 모듈을 통해 관리되며, 결제 정보는 Payment 객체에 담겨 반한된다. \ No newline at end of file +- [x] 유료 강의의 경우 결제는 이미 완료한 것으로 가정하고 이후 과정을 구현한다. +- [x] 결제를 완료한 결제 정보는 payments 모듈을 통해 관리되며, 결제 정보는 Payment 객체에 담겨 반한된다. \ No newline at end of file diff --git a/src/main/java/nextstep/payments/domain/Payments.java b/src/main/java/nextstep/payments/domain/Payments.java new file mode 100644 index 000000000..0fe1bba9b --- /dev/null +++ b/src/main/java/nextstep/payments/domain/Payments.java @@ -0,0 +1,20 @@ +package nextstep.payments.domain; + +import java.util.ArrayList; +import java.util.List; + +public class Payments { + private final List payments; + + public Payments() { + this.payments = new ArrayList<>(); + } + + public void add(Payment payment) { + payments.add(payment); + } + + public int size() { + return payments.size(); + } +} diff --git a/src/test/java/nextstep/courses/domain/SessionFixture.java b/src/test/java/fixture/sessions/domain/SessionFixture.java similarity index 96% rename from src/test/java/nextstep/courses/domain/SessionFixture.java rename to src/test/java/fixture/sessions/domain/SessionFixture.java index f620e3241..6ea3dfb0a 100644 --- a/src/test/java/nextstep/courses/domain/SessionFixture.java +++ b/src/test/java/fixture/sessions/domain/SessionFixture.java @@ -1,4 +1,4 @@ -package nextstep.courses.domain; +package fixture.sessions.domain; import nextstep.sessions.domain.ChargeStatus; import nextstep.sessions.domain.Session; diff --git a/src/test/java/nextstep/courses/domain/CourseTest.java b/src/test/java/nextstep/courses/domain/CourseTest.java index 03f008eb3..8680c2f38 100644 --- a/src/test/java/nextstep/courses/domain/CourseTest.java +++ b/src/test/java/nextstep/courses/domain/CourseTest.java @@ -1,5 +1,6 @@ package nextstep.courses.domain; +import fixture.sessions.domain.SessionFixture; import nextstep.sessions.domain.*; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; diff --git a/src/test/java/nextstep/payment/domain/PaymentTest.java b/src/test/java/nextstep/payment/domain/PaymentTest.java new file mode 100644 index 000000000..b8321904d --- /dev/null +++ b/src/test/java/nextstep/payment/domain/PaymentTest.java @@ -0,0 +1,35 @@ +package nextstep.payment.domain; + +import nextstep.payments.domain.Payment; +import nextstep.payments.domain.Payments; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class PaymentTest { + + @DisplayName("결제를 한다.") + @Test + void createPayment() { + // given&when + Payment payment = new Payment("1", 1L, 1L, 100L); + // then + assertThat(payment.getAmount()).isEqualTo(100L); + } + @DisplayName("결제를 완료한 결제 정보는 payments에 저장한다.") + @Test + void createPayments() { + // given + Payment payment1 = new Payment("1", 1L, 1L, 100L); + Payment payment2 = new Payment("1", 1L, 1L, 100L); + + // when + Payments payments = new Payments(); + payments.add(payment1); + payments.add(payment2); + + // then + assertThat(payments.size()).isEqualTo(2); + } +} diff --git a/src/test/java/nextstep/courses/domain/ChargeTest.java b/src/test/java/nextstep/sessions/domain/ChargeTest.java similarity index 86% rename from src/test/java/nextstep/courses/domain/ChargeTest.java rename to src/test/java/nextstep/sessions/domain/ChargeTest.java index 48eba4aec..d27357b3a 100644 --- a/src/test/java/nextstep/courses/domain/ChargeTest.java +++ b/src/test/java/nextstep/sessions/domain/ChargeTest.java @@ -1,7 +1,5 @@ -package nextstep.courses.domain; +package nextstep.sessions.domain; -import nextstep.sessions.domain.Charge; -import nextstep.sessions.domain.ChargeStatus; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; diff --git a/src/test/java/nextstep/courses/domain/EnrollmentTest.java b/src/test/java/nextstep/sessions/domain/EnrollmentTest.java similarity index 93% rename from src/test/java/nextstep/courses/domain/EnrollmentTest.java rename to src/test/java/nextstep/sessions/domain/EnrollmentTest.java index 90dda402e..0d0e32a38 100644 --- a/src/test/java/nextstep/courses/domain/EnrollmentTest.java +++ b/src/test/java/nextstep/sessions/domain/EnrollmentTest.java @@ -1,7 +1,5 @@ -package nextstep.courses.domain; +package nextstep.sessions.domain; -import nextstep.sessions.domain.Enrollment; -import nextstep.sessions.domain.SessionStatus; import nextstep.users.domain.NsUserTest; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; diff --git a/src/test/java/nextstep/courses/domain/ImageTest.java b/src/test/java/nextstep/sessions/domain/ImageTest.java similarity index 98% rename from src/test/java/nextstep/courses/domain/ImageTest.java rename to src/test/java/nextstep/sessions/domain/ImageTest.java index da8fdac8f..6a77ff0e5 100644 --- a/src/test/java/nextstep/courses/domain/ImageTest.java +++ b/src/test/java/nextstep/sessions/domain/ImageTest.java @@ -1,4 +1,4 @@ -package nextstep.courses.domain; +package nextstep.sessions.domain; import nextstep.image.domain.ImageHeight; import nextstep.image.domain.ImageShape; diff --git a/src/test/java/nextstep/sessions/domain/SessionTest.java b/src/test/java/nextstep/sessions/domain/SessionTest.java index 1f2f63605..e28695656 100644 --- a/src/test/java/nextstep/sessions/domain/SessionTest.java +++ b/src/test/java/nextstep/sessions/domain/SessionTest.java @@ -5,7 +5,7 @@ import java.time.LocalDate; -import static nextstep.courses.domain.SessionFixture.*; +import static fixture.sessions.domain.SessionFixture.*; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.AssertionsForClassTypes.assertThatExceptionOfType; From 91cfaef3e31ddde4bf2bb56e383bda62b9c85753 Mon Sep 17 00:00:00 2001 From: Sangmin Date: Mon, 22 Apr 2024 13:48:39 +0900 Subject: [PATCH 19/24] =?UTF-8?q?test:=20=EA=B2=B0=EC=A0=9C=EA=B8=88?= =?UTF-8?q?=EC=95=A1=EA=B3=BC=20=EA=B0=95=EC=9D=98=EA=B8=88=EC=95=A1?= =?UTF-8?q?=EC=9D=B4=20=EB=8B=A4=EB=A5=B4=EB=A9=B4=20=EA=B2=B0=EC=A0=9C?= =?UTF-8?q?=EA=B0=80=20=EB=90=98=EC=A7=80=20=EC=95=8A=EB=8A=94=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../nextstep/payments/domain/Payment.java | 5 ++++- .../nextstep/payment/domain/PaymentTest.java | 20 ++++++++++++++++--- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/src/main/java/nextstep/payments/domain/Payment.java b/src/main/java/nextstep/payments/domain/Payment.java index 443899865..7d7aeae3e 100644 --- a/src/main/java/nextstep/payments/domain/Payment.java +++ b/src/main/java/nextstep/payments/domain/Payment.java @@ -19,7 +19,10 @@ public class Payment { public Payment() { } - public Payment(String id, Long sessionId, Long nsUserId, Long amount) { + public Payment(String id, Long sessionId, Long nsUserId, Long amount, Long sessionAmount) { + if (!amount.equals(sessionAmount)) { + throw new IllegalArgumentException("결제 금액이 강의 금액과 일치하지 않습니다."); + } this.id = id; this.sessionId = sessionId; this.nsUserId = nsUserId; diff --git a/src/test/java/nextstep/payment/domain/PaymentTest.java b/src/test/java/nextstep/payment/domain/PaymentTest.java index b8321904d..a2639df3d 100644 --- a/src/test/java/nextstep/payment/domain/PaymentTest.java +++ b/src/test/java/nextstep/payment/domain/PaymentTest.java @@ -2,10 +2,13 @@ import nextstep.payments.domain.Payment; import nextstep.payments.domain.Payments; +import nextstep.sessions.domain.Charge; +import nextstep.sessions.domain.ChargeStatus; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.AssertionsForClassTypes.assertThatExceptionOfType; public class PaymentTest { @@ -13,16 +16,27 @@ public class PaymentTest { @Test void createPayment() { // given&when - Payment payment = new Payment("1", 1L, 1L, 100L); + Payment payment = new Payment("1", 1L, 1L, 100L,100L); // then assertThat(payment.getAmount()).isEqualTo(100L); } + + @DisplayName("결제금액과 강의금액이 다르면 결제가 되지 않는다.") + @Test + void createPaymentWithNotEqualAmount() { + // given&when&then + assertThatExceptionOfType(IllegalArgumentException.class) + .isThrownBy(() -> { + new Payment("1", 1L, 1L, 100L,101L); + }).withMessageMatching("결제 금액이 강의 금액과 일치하지 않습니다."); + } + @DisplayName("결제를 완료한 결제 정보는 payments에 저장한다.") @Test void createPayments() { // given - Payment payment1 = new Payment("1", 1L, 1L, 100L); - Payment payment2 = new Payment("1", 1L, 1L, 100L); + Payment payment1 = new Payment("1", 1L, 1L, 100L, 100L); + Payment payment2 = new Payment("1", 1L, 1L, 100L, 100L); // when Payments payments = new Payments(); From fdf3e6d84eb6dbcb56ac878f895cf03a1577f5d9 Mon Sep 17 00:00:00 2001 From: Sangmin Date: Mon, 22 Apr 2024 13:53:42 +0900 Subject: [PATCH 20/24] =?UTF-8?q?refactor:=20Payment=20=EC=83=9D=EC=84=B1?= =?UTF-8?q?=EC=9E=90=EC=97=90=20ChargeStatus=20=EC=9D=B8=EC=88=98=EA=B0=92?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/nextstep/payments/domain/Payment.java | 6 ++++-- src/test/java/nextstep/payment/domain/PaymentTest.java | 9 ++++----- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/main/java/nextstep/payments/domain/Payment.java b/src/main/java/nextstep/payments/domain/Payment.java index 7d7aeae3e..c8dda137e 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.sessions.domain.ChargeStatus; + import java.time.LocalDateTime; public class Payment { @@ -19,8 +21,8 @@ public class Payment { public Payment() { } - public Payment(String id, Long sessionId, Long nsUserId, Long amount, Long sessionAmount) { - if (!amount.equals(sessionAmount)) { + public Payment(String id, Long sessionId, Long nsUserId, Long amount, Long sessionAmount, ChargeStatus chargeStatus) { + if (chargeStatus.equals(ChargeStatus.PAID) && !amount.equals(sessionAmount)) { throw new IllegalArgumentException("결제 금액이 강의 금액과 일치하지 않습니다."); } this.id = id; diff --git a/src/test/java/nextstep/payment/domain/PaymentTest.java b/src/test/java/nextstep/payment/domain/PaymentTest.java index a2639df3d..ab70d8115 100644 --- a/src/test/java/nextstep/payment/domain/PaymentTest.java +++ b/src/test/java/nextstep/payment/domain/PaymentTest.java @@ -2,7 +2,6 @@ import nextstep.payments.domain.Payment; import nextstep.payments.domain.Payments; -import nextstep.sessions.domain.Charge; import nextstep.sessions.domain.ChargeStatus; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -16,7 +15,7 @@ public class PaymentTest { @Test void createPayment() { // given&when - Payment payment = new Payment("1", 1L, 1L, 100L,100L); + Payment payment = new Payment("1", 1L, 1L, 100L,100L, ChargeStatus.PAID); // then assertThat(payment.getAmount()).isEqualTo(100L); } @@ -27,7 +26,7 @@ void createPaymentWithNotEqualAmount() { // given&when&then assertThatExceptionOfType(IllegalArgumentException.class) .isThrownBy(() -> { - new Payment("1", 1L, 1L, 100L,101L); + new Payment("1", 1L, 1L, 100L,101L, ChargeStatus.PAID); }).withMessageMatching("결제 금액이 강의 금액과 일치하지 않습니다."); } @@ -35,8 +34,8 @@ void createPaymentWithNotEqualAmount() { @Test void createPayments() { // given - Payment payment1 = new Payment("1", 1L, 1L, 100L, 100L); - Payment payment2 = new Payment("1", 1L, 1L, 100L, 100L); + Payment payment1 = new Payment("1", 1L, 1L, 100L, 100L, ChargeStatus.PAID); + Payment payment2 = new Payment("1", 1L, 1L, 100L, 100L, ChargeStatus.PAID); // when Payments payments = new Payments(); From d58ad382d1820a69f8659b9bb809f71aa8d87163 Mon Sep 17 00:00:00 2001 From: Sangmin Date: Mon, 29 Apr 2024 19:27:54 +0900 Subject: [PATCH 21/24] =?UTF-8?q?feat:=20sessionRepository=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/nextstep/image/domain/Image.java | 8 ++- .../image/domain/ImageRepository.java | 6 ++ .../infrastructure/JdbcImageRepository.java | 23 ++++++ .../java/nextstep/sessions/domain/Charge.java | 8 +++ .../nextstep/sessions/domain/Enrollment.java | 11 +++ .../nextstep/sessions/domain/Session.java | 44 +++++++++--- .../nextstep/sessions/domain/SessionDate.java | 8 +++ .../nextstep/sessions/domain/SessionInfo.java | 12 ++++ .../sessions/domain/SessionRepository.java | 6 ++ .../infrastructure/JdbcSessionRepository.java | 72 +++++++++++++++++++ .../sessions/domain/SessionFixture.java | 4 +- .../nextstep/sessions/domain/SessionTest.java | 3 +- .../infrastructure/SessionRepositoryTest.java | 41 +++++++++++ 13 files changed, 232 insertions(+), 14 deletions(-) create mode 100644 src/main/java/nextstep/image/domain/ImageRepository.java create mode 100644 src/main/java/nextstep/image/infrastructure/JdbcImageRepository.java create mode 100644 src/main/java/nextstep/sessions/domain/SessionRepository.java create mode 100644 src/main/java/nextstep/sessions/infrastructure/JdbcSessionRepository.java create mode 100644 src/test/java/nextstep/sessions/infrastructure/SessionRepositoryTest.java diff --git a/src/main/java/nextstep/image/domain/Image.java b/src/main/java/nextstep/image/domain/Image.java index cc75f4be4..f28138a97 100644 --- a/src/main/java/nextstep/image/domain/Image.java +++ b/src/main/java/nextstep/image/domain/Image.java @@ -1,11 +1,17 @@ package nextstep.image.domain; public class Image { + private Long id; + private Long sessionId; + private String url; private ImageType type; private ImageShape shape; private Integer size; - public Image(final ImageType type, final ImageShape shape, final Integer size) { + public Image(final long id, final long sessionId, final String url, final ImageType type, final ImageShape shape, final Integer size) { + this.id = id; + this.sessionId = sessionId; + this.url = url; this.type = type; this.shape = shape; this.size = size; diff --git a/src/main/java/nextstep/image/domain/ImageRepository.java b/src/main/java/nextstep/image/domain/ImageRepository.java new file mode 100644 index 000000000..08bb55cb9 --- /dev/null +++ b/src/main/java/nextstep/image/domain/ImageRepository.java @@ -0,0 +1,6 @@ +package nextstep.image.domain; + +public interface ImageRepository { + int save(final Image image); + Image findById(Long id); +} diff --git a/src/main/java/nextstep/image/infrastructure/JdbcImageRepository.java b/src/main/java/nextstep/image/infrastructure/JdbcImageRepository.java new file mode 100644 index 000000000..8d9daec32 --- /dev/null +++ b/src/main/java/nextstep/image/infrastructure/JdbcImageRepository.java @@ -0,0 +1,23 @@ +package nextstep.image.infrastructure; + +import nextstep.image.domain.Image; +import nextstep.image.domain.ImageRepository; +import org.springframework.jdbc.core.JdbcOperations; + +public class JdbcImageRepository implements ImageRepository { + private JdbcOperations jdbcTemplate; + + public JdbcImageRepository(JdbcOperations jdbcTemplate) { + this.jdbcTemplate = jdbcTemplate; + } + + @Override + public int save(final Image image) { + return 0; + } + + @Override + public Image findById(final Long id) { + return null; + } +} diff --git a/src/main/java/nextstep/sessions/domain/Charge.java b/src/main/java/nextstep/sessions/domain/Charge.java index e164c8b88..b2ec798fc 100644 --- a/src/main/java/nextstep/sessions/domain/Charge.java +++ b/src/main/java/nextstep/sessions/domain/Charge.java @@ -14,4 +14,12 @@ public Charge(ChargeStatus status, int price) { this.status = status; this.price = price; } + + public ChargeStatus getStatus() { + return status; + } + + public int getPrice() { + return price; + } } diff --git a/src/main/java/nextstep/sessions/domain/Enrollment.java b/src/main/java/nextstep/sessions/domain/Enrollment.java index 1d788b776..0c0c564f5 100644 --- a/src/main/java/nextstep/sessions/domain/Enrollment.java +++ b/src/main/java/nextstep/sessions/domain/Enrollment.java @@ -41,4 +41,15 @@ private boolean isFullCapacity() { return students.size() == capacity; } + public SessionStatus getSessionStatus() { + return sessionStatus; + } + + public int getCapacity() { + return capacity; + } + + public List getStudents() { + return students; + } } diff --git a/src/main/java/nextstep/sessions/domain/Session.java b/src/main/java/nextstep/sessions/domain/Session.java index ea1891a05..733982e39 100644 --- a/src/main/java/nextstep/sessions/domain/Session.java +++ b/src/main/java/nextstep/sessions/domain/Session.java @@ -4,25 +4,51 @@ public class Session { - private final SessionInfo sessionInfo; - private final Charge charge; + private final Long id; + private final SessionInfo sessionInfo; + private final Charge charge; private final Enrollment enrollment; - private final SessionDate sessionDate; + private final SessionDate sessionDate; - public Session(String title, Long creatorId, - ChargeStatus chargeStatus, int price, - int capacity, SessionStatus sessionStatus, - LocalDate startDate, LocalDate endDate) { - this(new SessionInfo(title, creatorId, null), + public Session(final Long id, String title, Long creatorId, + ChargeStatus chargeStatus, int price, + int capacity, SessionStatus sessionStatus, + LocalDate startDate, LocalDate endDate) { + this(id, new SessionInfo(title, creatorId, null), new Charge(chargeStatus, price), new Enrollment(sessionStatus, capacity), new SessionDate(new StartedAt(startDate), new EndedAt(endDate))); } - public Session(SessionInfo sessionInfo, Charge charge, Enrollment enrollment, SessionDate sessionDate) { + public Session(final Long id, SessionInfo sessionInfo, Charge charge, Enrollment enrollment, SessionDate sessionDate) { + this.id = id; this.sessionInfo = sessionInfo; this.charge = charge; this.enrollment = enrollment; this.sessionDate = sessionDate; } + + public String getTitle() { + return sessionInfo.getTitle(); + } + + public Long getCreatorId() { + return sessionInfo.getCreatorId(); + } + + public ChargeStatus getChargeStatus() { + return charge.getStatus(); + } + + public int getPrice() { + return charge.getPrice(); + } + + public LocalDate getStartedAt() { + return sessionDate.getStartedAt(); + } + + public LocalDate getEndedAt() { + return sessionDate.getEndedAt(); + } } diff --git a/src/main/java/nextstep/sessions/domain/SessionDate.java b/src/main/java/nextstep/sessions/domain/SessionDate.java index 124d8504e..aa8ce910f 100644 --- a/src/main/java/nextstep/sessions/domain/SessionDate.java +++ b/src/main/java/nextstep/sessions/domain/SessionDate.java @@ -18,4 +18,12 @@ private static void validateSessionDate(final LocalDate startedAt, final LocalDa throw new IllegalArgumentException("강의 종료일보다 강의 시작일이 늦을 수 없습니다."); } } + + public LocalDate getStartedAt() { + return startedAt.getStartedAt(); + } + + public LocalDate getEndedAt() { + return endedAt.getEndedAt(); + } } diff --git a/src/main/java/nextstep/sessions/domain/SessionInfo.java b/src/main/java/nextstep/sessions/domain/SessionInfo.java index b649413c1..5a0eecc62 100644 --- a/src/main/java/nextstep/sessions/domain/SessionInfo.java +++ b/src/main/java/nextstep/sessions/domain/SessionInfo.java @@ -13,4 +13,16 @@ public SessionInfo(String title, Long creatorId, Image image) { this.creatorId = creatorId; this.image = image; } + + public String getTitle() { + return title; + } + + public Long getCreatorId() { + return creatorId; + } + + public Image getImage() { + return image; + } } diff --git a/src/main/java/nextstep/sessions/domain/SessionRepository.java b/src/main/java/nextstep/sessions/domain/SessionRepository.java new file mode 100644 index 000000000..d7a04115c --- /dev/null +++ b/src/main/java/nextstep/sessions/domain/SessionRepository.java @@ -0,0 +1,6 @@ +package nextstep.sessions.domain; + +public interface SessionRepository { + int save(final Session session); + Session findById(Long id); +} diff --git a/src/main/java/nextstep/sessions/infrastructure/JdbcSessionRepository.java b/src/main/java/nextstep/sessions/infrastructure/JdbcSessionRepository.java new file mode 100644 index 000000000..e137a9050 --- /dev/null +++ b/src/main/java/nextstep/sessions/infrastructure/JdbcSessionRepository.java @@ -0,0 +1,72 @@ +package nextstep.sessions.infrastructure; + +import nextstep.image.domain.*; +import nextstep.sessions.domain.*; +import org.springframework.jdbc.core.JdbcOperations; +import org.springframework.jdbc.core.RowMapper; + +import java.sql.Timestamp; +import java.time.LocalDate; +import java.util.List; + +public class JdbcSessionRepository implements SessionRepository { + private JdbcOperations jdbcTemplate; + + public JdbcSessionRepository(JdbcOperations jdbcTemplate) { + this.jdbcTemplate = jdbcTemplate; + } + + @Override + public int save(Session session) { + String sql = "insert into session (title, creator_id, price, charge_status, start_at, ended_at) values(?, ?, ?)"; + return jdbcTemplate.update(sql, session.getTitle(), session.getCreatorId(), session.getPrice(), session.getChargeStatus(), session.getStartedAt(), session.getEndedAt()); + } + + @Override + public Session findById(Long id) { + String sql = "select session.id, session.title, session.creator_id, image.id, image.session_id, image.url, image.image_type, image.width, image.height, image.size, session.created_at, session.updated_at " + + "from session left outer join image on image.session_id = session.id" + + " left outer join user on session.id = user.session_id" + + " where id = ?"; + RowMapper rowMapper = (rs, rowNum) -> new Session( + rs.getLong(1), + new SessionInfo( + rs.getString(2), + rs.getLong(3), + new Image( + rs.getLong(4), + rs.getLong(5), + rs.getString(6), + ImageType.valueOf(rs.getString(7)), + new ImageShape( + new ImageWidth(rs.getInt(8)), + new ImageHeight(rs.getInt(9)) + ), + rs.getInt(10) + ) + ), + new Charge( + ChargeStatus.valueOf(rs.getString(11)), + rs.getInt(12) + ), + new Enrollment( + SessionStatus.valueOf(rs.getString(13)), + rs.getInt(14), + rs.getObject(15, List.class) + ), + new SessionDate( + new StartedAt(toLocalDate(rs.getTimestamp(5))), + new EndedAt(toLocalDate(rs.getTimestamp(6))) + ) + + ); + return jdbcTemplate.queryForObject(sql, rowMapper, id); + } + + private LocalDate toLocalDate(Timestamp timestamp) { + if (timestamp == null) { + return null; + } + return timestamp.toLocalDateTime().toLocalDate(); + } +} diff --git a/src/test/java/fixture/sessions/domain/SessionFixture.java b/src/test/java/fixture/sessions/domain/SessionFixture.java index 6ea3dfb0a..f687dc06f 100644 --- a/src/test/java/fixture/sessions/domain/SessionFixture.java +++ b/src/test/java/fixture/sessions/domain/SessionFixture.java @@ -8,14 +8,14 @@ public class SessionFixture { public static Session createSessionWithEnrollment(int capacity, SessionStatus status) { - return new Session( + return new Session(1L, "TDD, 클린 코드 with Java 16기", 2L, ChargeStatus.PAID, 800_000, capacity, status, LocalDate.now(), LocalDate.now().plusDays(30)); } public static Session createSessionWithSessionDate(LocalDate startDate, LocalDate endDate) { - return new Session( + return new Session(1L, "TDD, 클린 코드 with Java 16기", 2L, ChargeStatus.PAID, 800_000, 10, SessionStatus.OPENED, diff --git a/src/test/java/nextstep/sessions/domain/SessionTest.java b/src/test/java/nextstep/sessions/domain/SessionTest.java index e28695656..e113af3b6 100644 --- a/src/test/java/nextstep/sessions/domain/SessionTest.java +++ b/src/test/java/nextstep/sessions/domain/SessionTest.java @@ -5,8 +5,7 @@ import java.time.LocalDate; -import static fixture.sessions.domain.SessionFixture.*; -import static org.assertj.core.api.Assertions.assertThat; +import static fixture.sessions.domain.SessionFixture.createSessionWithSessionDate; import static org.assertj.core.api.AssertionsForClassTypes.assertThatExceptionOfType; public class SessionTest { diff --git a/src/test/java/nextstep/sessions/infrastructure/SessionRepositoryTest.java b/src/test/java/nextstep/sessions/infrastructure/SessionRepositoryTest.java new file mode 100644 index 000000000..265dbf867 --- /dev/null +++ b/src/test/java/nextstep/sessions/infrastructure/SessionRepositoryTest.java @@ -0,0 +1,41 @@ +package nextstep.sessions.infrastructure; + +import fixture.sessions.domain.SessionFixture; +import nextstep.courses.infrastructure.CourseRepositoryTest; +import nextstep.sessions.domain.Session; +import nextstep.sessions.domain.SessionRepository; +import nextstep.sessions.domain.SessionStatus; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.jdbc.JdbcTest; +import org.springframework.jdbc.core.JdbcTemplate; + +import static org.assertj.core.api.Assertions.assertThat; + +@JdbcTest +public class SessionRepositoryTest { + private static final Logger LOGGER = LoggerFactory.getLogger(CourseRepositoryTest.class); + + @Autowired + private JdbcTemplate jdbcTemplate; + + private SessionRepository sessionRepository; + + @BeforeEach + void setUp() { + sessionRepository = new JdbcSessionRepository(jdbcTemplate); + } + + @Test + void crud() { + Session session = SessionFixture.createSessionWithEnrollment(50, SessionStatus.OPENED); + int count = sessionRepository.save(session); + assertThat(count).isEqualTo(1); + Session savedSession = sessionRepository.findById(1L); + assertThat(savedSession.getTitle()).isEqualTo(session.getTitle()); + LOGGER.debug("Course: {}", savedSession); + } +} From 00ce7b2d0a5e4d1d9d03c85bfb63bb0897fd1033 Mon Sep 17 00:00:00 2001 From: Sangmin Date: Fri, 3 May 2024 13:33:18 +0900 Subject: [PATCH 22/24] =?UTF-8?q?test:=20imageRepositoryTest=20=EC=99=84?= =?UTF-8?q?=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/nextstep/image/domain/Image.java | 24 +++++++++++ .../image/domain/ImageRepository.java | 2 +- .../nextstep/image/domain/ImageShape.java | 12 ++++++ .../infrastructure/JdbcImageRepository.java | 32 ++++++++++++--- src/main/resources/schema.sql | 11 +++++ .../{sessions => image}/domain/ImageTest.java | 6 +-- .../infrastructure/ImageRepositoryTest.java | 40 +++++++++++++++++++ 7 files changed, 115 insertions(+), 12 deletions(-) rename src/test/java/nextstep/{sessions => image}/domain/ImageTest.java (90%) create mode 100644 src/test/java/nextstep/image/infrastructure/ImageRepositoryTest.java diff --git a/src/main/java/nextstep/image/domain/Image.java b/src/main/java/nextstep/image/domain/Image.java index f28138a97..5dc7023e0 100644 --- a/src/main/java/nextstep/image/domain/Image.java +++ b/src/main/java/nextstep/image/domain/Image.java @@ -16,4 +16,28 @@ public Image(final long id, final long sessionId, final String url, final ImageT this.shape = shape; this.size = size; } + + public Long getSessionId() { + return sessionId; + } + + public String getUrl() { + return url; + } + + public String getType() { + return type.name(); + } + + public int getImageWidth() { + return shape.getWidth(); + } + + public int getImageHeight() { + return shape.getHeight(); + } + + public int getSize() { + return size; + } } diff --git a/src/main/java/nextstep/image/domain/ImageRepository.java b/src/main/java/nextstep/image/domain/ImageRepository.java index 08bb55cb9..bd15c1dd1 100644 --- a/src/main/java/nextstep/image/domain/ImageRepository.java +++ b/src/main/java/nextstep/image/domain/ImageRepository.java @@ -2,5 +2,5 @@ public interface ImageRepository { int save(final Image image); - Image findById(Long id); + Image findById(final Long id); } diff --git a/src/main/java/nextstep/image/domain/ImageShape.java b/src/main/java/nextstep/image/domain/ImageShape.java index 213dbde60..316e817dd 100644 --- a/src/main/java/nextstep/image/domain/ImageShape.java +++ b/src/main/java/nextstep/image/domain/ImageShape.java @@ -4,6 +4,10 @@ public class ImageShape { private ImageWidth width; private ImageHeight height; + public ImageShape(final int width, final int height) { + this(new ImageWidth(width), new ImageHeight(height)); + } + public ImageShape(ImageWidth width, ImageHeight height) { validateShape(width, height); this.width = width; @@ -15,4 +19,12 @@ private static void validateShape(final ImageWidth width, final ImageHeight heig throw new IllegalArgumentException("가로 세로 비율은 3:2이어야 합니다."); } } + + public int getWidth() { + return width.getWidth(); + } + + public int getHeight() { + return height.getHeight(); + } } diff --git a/src/main/java/nextstep/image/infrastructure/JdbcImageRepository.java b/src/main/java/nextstep/image/infrastructure/JdbcImageRepository.java index 8d9daec32..c364a5251 100644 --- a/src/main/java/nextstep/image/infrastructure/JdbcImageRepository.java +++ b/src/main/java/nextstep/image/infrastructure/JdbcImageRepository.java @@ -1,8 +1,12 @@ package nextstep.image.infrastructure; -import nextstep.image.domain.Image; -import nextstep.image.domain.ImageRepository; +import nextstep.courses.domain.Course; +import nextstep.image.domain.*; import org.springframework.jdbc.core.JdbcOperations; +import org.springframework.jdbc.core.RowMapper; + +import java.sql.Timestamp; +import java.time.LocalDateTime; public class JdbcImageRepository implements ImageRepository { private JdbcOperations jdbcTemplate; @@ -12,12 +16,28 @@ public JdbcImageRepository(JdbcOperations jdbcTemplate) { } @Override - public int save(final Image image) { - return 0; + public int save(Image image) { + String sql = "insert into image (session_id, url, image_type, image_height, image_width, size) values(?, ?, ?,?, ?, ?)"; + return jdbcTemplate.update(sql, image.getSessionId(), image.getUrl(), image.getType(), image.getImageHeight(), image.getImageWidth(), image.getSize()); } @Override - public Image findById(final Long id) { - return null; + public Image findById(Long id) { + String sql = "select id, session_id, url, image_type, image_width, image_height, size from image where id = ?"; + RowMapper rowMapper = (rs, rowNum) -> new Image( + rs.getLong(1), + rs.getLong(2), + rs.getString(3), + ImageType.valueOf(rs.getString(4)), + new ImageShape(rs.getInt(5), rs.getInt(6)), + rs.getInt(7)); + return jdbcTemplate.queryForObject(sql, rowMapper, id); + } + + private LocalDateTime toLocalDateTime(Timestamp timestamp) { + if (timestamp == null) { + return null; + } + return timestamp.toLocalDateTime(); } } diff --git a/src/main/resources/schema.sql b/src/main/resources/schema.sql index 8d5a988c8..f20e9079f 100644 --- a/src/main/resources/schema.sql +++ b/src/main/resources/schema.sql @@ -48,3 +48,14 @@ create table delete_history ( deleted_by_id bigint, primary key (id) ); + +create table image ( + id bigint generated by default as identity, + session_id bigint not null, + url varchar(255), + image_type varchar(255), + image_width bigint, + image_height bigint, + size bigint, + primary key (id) +); diff --git a/src/test/java/nextstep/sessions/domain/ImageTest.java b/src/test/java/nextstep/image/domain/ImageTest.java similarity index 90% rename from src/test/java/nextstep/sessions/domain/ImageTest.java rename to src/test/java/nextstep/image/domain/ImageTest.java index 6a77ff0e5..8c2986035 100644 --- a/src/test/java/nextstep/sessions/domain/ImageTest.java +++ b/src/test/java/nextstep/image/domain/ImageTest.java @@ -1,9 +1,5 @@ -package nextstep.sessions.domain; +package nextstep.image.domain; -import nextstep.image.domain.ImageHeight; -import nextstep.image.domain.ImageShape; -import nextstep.image.domain.ImageSize; -import nextstep.image.domain.ImageWidth; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; diff --git a/src/test/java/nextstep/image/infrastructure/ImageRepositoryTest.java b/src/test/java/nextstep/image/infrastructure/ImageRepositoryTest.java new file mode 100644 index 000000000..31a1e06e1 --- /dev/null +++ b/src/test/java/nextstep/image/infrastructure/ImageRepositoryTest.java @@ -0,0 +1,40 @@ +package nextstep.image.infrastructure; + +import nextstep.image.domain.Image; +import nextstep.image.domain.ImageRepository; +import nextstep.image.domain.ImageShape; +import nextstep.image.domain.ImageType; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.jdbc.JdbcTest; +import org.springframework.jdbc.core.JdbcTemplate; + +import static org.assertj.core.api.Assertions.assertThat; + +@JdbcTest +public class ImageRepositoryTest { + private static final Logger LOGGER = LoggerFactory.getLogger(ImageRepositoryTest.class); + + @Autowired + private JdbcTemplate jdbcTemplate; + + private ImageRepository imageRepository; + + @BeforeEach + void setUp() { + imageRepository = new JdbcImageRepository(jdbcTemplate); + } + + @Test + void crud() { + Image image = new Image(1L, 1L, "image1.png", ImageType.GIF, new ImageShape(1200, 800), 100); + int count = imageRepository.save(image); + assertThat(count).isEqualTo(1); + Image savedImage = imageRepository.findById(1L); + assertThat(savedImage.getUrl()).isEqualTo(image.getUrl()); + LOGGER.debug("Image: {}", savedImage); + } +} From 5bd64048d5c4ef7d7d70bbce83e705a9f9b34b32 Mon Sep 17 00:00:00 2001 From: Sangmin Date: Fri, 3 May 2024 20:23:04 +0900 Subject: [PATCH 23/24] =?UTF-8?q?test:=20sessionRepositoryTest=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/nextstep/sessions/domain/Session.java | 12 ++++++++++-- .../infrastructure/JdbcSessionRepository.java | 8 ++++---- src/main/resources/schema.sql | 13 +++++++++++++ 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/src/main/java/nextstep/sessions/domain/Session.java b/src/main/java/nextstep/sessions/domain/Session.java index 733982e39..680e69d6c 100644 --- a/src/main/java/nextstep/sessions/domain/Session.java +++ b/src/main/java/nextstep/sessions/domain/Session.java @@ -36,8 +36,8 @@ public Long getCreatorId() { return sessionInfo.getCreatorId(); } - public ChargeStatus getChargeStatus() { - return charge.getStatus(); + public String getChargeStatus() { + return charge.getStatus().name(); } public int getPrice() { @@ -51,4 +51,12 @@ public LocalDate getStartedAt() { public LocalDate getEndedAt() { return sessionDate.getEndedAt(); } + + public String getSessionStatus() { + return enrollment.getSessionStatus().name(); + } + + public int getCapacity() { + return enrollment.getCapacity(); + } } diff --git a/src/main/java/nextstep/sessions/infrastructure/JdbcSessionRepository.java b/src/main/java/nextstep/sessions/infrastructure/JdbcSessionRepository.java index e137a9050..b630b030b 100644 --- a/src/main/java/nextstep/sessions/infrastructure/JdbcSessionRepository.java +++ b/src/main/java/nextstep/sessions/infrastructure/JdbcSessionRepository.java @@ -18,8 +18,8 @@ public JdbcSessionRepository(JdbcOperations jdbcTemplate) { @Override public int save(Session session) { - String sql = "insert into session (title, creator_id, price, charge_status, start_at, ended_at) values(?, ?, ?)"; - return jdbcTemplate.update(sql, session.getTitle(), session.getCreatorId(), session.getPrice(), session.getChargeStatus(), session.getStartedAt(), session.getEndedAt()); + String sql = "insert into session (title, creator_id, charge_status, price, session_status, capacity, started_at, ended_at) values(?, ?, ?,?, ?, ?, ?, ?)"; + return jdbcTemplate.update(sql, session.getTitle(), session.getCreatorId(),session.getChargeStatus(), session.getPrice(), session.getSessionStatus(), session.getCapacity(), session.getStartedAt(), session.getEndedAt()); } @Override @@ -55,8 +55,8 @@ public Session findById(Long id) { rs.getObject(15, List.class) ), new SessionDate( - new StartedAt(toLocalDate(rs.getTimestamp(5))), - new EndedAt(toLocalDate(rs.getTimestamp(6))) + new StartedAt(toLocalDate(rs.getTimestamp(16))), + new EndedAt(toLocalDate(rs.getTimestamp(17))) ) ); diff --git a/src/main/resources/schema.sql b/src/main/resources/schema.sql index f20e9079f..8941e1509 100644 --- a/src/main/resources/schema.sql +++ b/src/main/resources/schema.sql @@ -59,3 +59,16 @@ create table image ( size bigint, primary key (id) ); + +create table session ( + id bigint generated by default as identity, + title varchar(255) not null, + creator_id bigint not null, + charge_status varchar(255) not null, + price bigint not null, + session_status varchar(255) not null, + capacity bigint not null, + started_at timestamp, + ended_at timestamp, + primary key (id) +); From 7eef947b1dc42bde620bb7bb73fa7e2a76443b0a Mon Sep 17 00:00:00 2001 From: Sangmin Date: Sat, 4 May 2024 00:42:55 +0900 Subject: [PATCH 24/24] =?UTF-8?q?test:=20sessionRepositoryTest=20=EC=99=84?= =?UTF-8?q?=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../infrastructure/JdbcSessionRepository.java | 47 +++++-------------- 1 file changed, 12 insertions(+), 35 deletions(-) diff --git a/src/main/java/nextstep/sessions/infrastructure/JdbcSessionRepository.java b/src/main/java/nextstep/sessions/infrastructure/JdbcSessionRepository.java index b630b030b..6c6a4af48 100644 --- a/src/main/java/nextstep/sessions/infrastructure/JdbcSessionRepository.java +++ b/src/main/java/nextstep/sessions/infrastructure/JdbcSessionRepository.java @@ -1,13 +1,11 @@ package nextstep.sessions.infrastructure; -import nextstep.image.domain.*; import nextstep.sessions.domain.*; import org.springframework.jdbc.core.JdbcOperations; import org.springframework.jdbc.core.RowMapper; import java.sql.Timestamp; import java.time.LocalDate; -import java.util.List; public class JdbcSessionRepository implements SessionRepository { private JdbcOperations jdbcTemplate; @@ -24,42 +22,21 @@ public int save(Session session) { @Override public Session findById(Long id) { - String sql = "select session.id, session.title, session.creator_id, image.id, image.session_id, image.url, image.image_type, image.width, image.height, image.size, session.created_at, session.updated_at " + - "from session left outer join image on image.session_id = session.id" + - " left outer join user on session.id = user.session_id" + - " where id = ?"; + String sql = "select session.id, session.title, session.creator_id, session.charge_status, session.price, session.capacity, session.session_status,session.started_at, session.ended_at " + + "from session where id = ?"; + RowMapper rowMapper = (rs, rowNum) -> new Session( rs.getLong(1), - new SessionInfo( - rs.getString(2), - rs.getLong(3), - new Image( - rs.getLong(4), - rs.getLong(5), - rs.getString(6), - ImageType.valueOf(rs.getString(7)), - new ImageShape( - new ImageWidth(rs.getInt(8)), - new ImageHeight(rs.getInt(9)) - ), - rs.getInt(10) - ) - ), - new Charge( - ChargeStatus.valueOf(rs.getString(11)), - rs.getInt(12) - ), - new Enrollment( - SessionStatus.valueOf(rs.getString(13)), - rs.getInt(14), - rs.getObject(15, List.class) - ), - new SessionDate( - new StartedAt(toLocalDate(rs.getTimestamp(16))), - new EndedAt(toLocalDate(rs.getTimestamp(17))) - ) - + rs.getString(2), + rs.getLong(3), + ChargeStatus.valueOf(rs.getString(4)), + rs.getInt(5), + rs.getInt(6), + SessionStatus.valueOf(rs.getString(7)), + toLocalDate(rs.getTimestamp(8)), + toLocalDate(rs.getTimestamp(9)) ); + return jdbcTemplate.queryForObject(sql, rowMapper, id); }