From c487fd5cec6e295292890bef69b3805e8723c60b Mon Sep 17 00:00:00 2001 From: june-777 Date: Sun, 11 Aug 2024 19:23:30 +0900 Subject: [PATCH 01/77] =?UTF-8?q?[feat]=20=EA=B8=B0=EB=8A=A5=20=EC=9A=94?= =?UTF-8?q?=EA=B5=AC=EC=82=AC=ED=95=AD=EC=97=90=20=EB=A7=9E=EA=B2=8C=20Sto?= =?UTF-8?q?re=20=EB=8F=84=EB=A9=94=EC=9D=B8=20=EC=97=94=ED=8B=B0=ED=8B=B0?= =?UTF-8?q?=EC=9D=98=20=EC=9D=B8=EC=8A=A4=ED=84=B4=EC=8A=A4=20=ED=95=84?= =?UTF-8?q?=EB=93=9C=20=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 기능 요구사항: 가게 이름, 전화번호, 위치 정보, 카테고리, 이용 시간, 최소 주문 금액을 입력해 가게를 등록 notice: - 카테고리 → StoreCategory 도메인 엔티티 - 주소 → Address 임베디드 타입 - 이용 시간 → StoreTime 임베디드 타입 - 도메인 생성 검증은 StoreValidator 에서 절차지향으로 진행 --- .../camp/woowak/lab/store/domain/Store.java | 64 +++++++++++++++++-- 1 file changed, 58 insertions(+), 6 deletions(-) diff --git a/src/main/java/camp/woowak/lab/store/domain/Store.java b/src/main/java/camp/woowak/lab/store/domain/Store.java index 9626c773..d2a19ade 100644 --- a/src/main/java/camp/woowak/lab/store/domain/Store.java +++ b/src/main/java/camp/woowak/lab/store/domain/Store.java @@ -1,13 +1,65 @@ package camp.woowak.lab.store.domain; +import java.time.LocalDateTime; + import camp.woowak.lab.vendor.domain.Vendor; -import jakarta.persistence.*; +import jakarta.persistence.Column; +import jakarta.persistence.Embedded; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToOne; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; @Entity +@NoArgsConstructor(access = AccessLevel.PROTECTED) public class Store { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - @ManyToOne(fetch = FetchType.LAZY) - private Vendor owner; + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "vendor_id", nullable = false) + private Vendor owner; + + @OneToOne + @JoinColumn(name = "store_category_id", nullable = false) + private StoreCategory storeCategory; + + @Column(nullable = false) + private String name; + + // TODO: 위치 정보에 대한 요구사항 논의 후 수정 예정. + // i.g) 송파구로 특정, 도시 정보로 특정 등 요구사항이 정의되어야 엔티티 설계를 진행할 수 있음 + @Embedded + private Address address; + + @Column(nullable = false) + private String phoneNumber; + + @Column(nullable = false) + private Integer minOrderPrice; + + @Embedded + private StoreTime storeTime; + + public Store(Vendor owner, StoreCategory storeCategory, String name, String address, String phoneNumber, + Integer minOrderPrice, LocalDateTime startTime, LocalDateTime endTime + ) { + StoreValidator.validate(name, address, minOrderPrice, startTime, endTime); + this.owner = owner; + this.storeCategory = storeCategory; + this.name = name; + this.address = new Address(address); + this.phoneNumber = phoneNumber; + this.minOrderPrice = minOrderPrice; + this.storeTime = new StoreTime(startTime, endTime); + } + } From 5daebb372996750afd986c8ff68be151b4e60801 Mon Sep 17 00:00:00 2001 From: june-777 Date: Sun, 11 Aug 2024 19:25:47 +0900 Subject: [PATCH 02/77] =?UTF-8?q?[feat]=20=EA=B0=80=EA=B2=8C=20=EC=9D=B4?= =?UTF-8?q?=EB=A6=84=20=EA=B2=80=EC=A6=9D=20=EA=B8=B0=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 가게 이름은 2글자 ~ 10글자만 가능 --- .../lab/store/domain/StoreValidator.java | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 src/main/java/camp/woowak/lab/store/domain/StoreValidator.java diff --git a/src/main/java/camp/woowak/lab/store/domain/StoreValidator.java b/src/main/java/camp/woowak/lab/store/domain/StoreValidator.java new file mode 100644 index 00000000..bae9d4ca --- /dev/null +++ b/src/main/java/camp/woowak/lab/store/domain/StoreValidator.java @@ -0,0 +1,29 @@ +package camp.woowak.lab.store.domain; + +import java.time.LocalDateTime; + +import camp.woowak.lab.store.exception.StoreException; + +public class StoreValidator { + + private static final int UNIT_OF_MIN_ORDER_PRICE = 1000; + + private static final int MIN_ORDER_PRICE = 5000; + + private static final int MIN_NAME_LENGTH = 2; + private static final int MAX_NAME_LENGTH = 10; + + public static void validate(final String name, final String address, final Integer minOrderPrice, + final LocalDateTime startTime, final LocalDateTime endTime + ) { + validateName(name); + } + + private static void validateName(final String name) { + if (MIN_NAME_LENGTH <= name.length() && name.length() <= MAX_NAME_LENGTH) { + return; + } + throw new StoreException("가게 이름은 2글자 ~ 10글자 이어야합니다."); + } + +} From f86bafeb57f37fec72a17b17af8d51d1c1b1b297 Mon Sep 17 00:00:00 2001 From: june-777 Date: Sun, 11 Aug 2024 19:27:37 +0900 Subject: [PATCH 03/77] =?UTF-8?q?[feat]=20=EA=B0=80=EA=B2=8C=20=EC=A3=BC?= =?UTF-8?q?=EC=86=8C=20=EA=B2=80=EC=A6=9D=20=EA=B8=B0=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 가게 주소는 송파구만 가능 - 추후 가게 위치 비즈니스 요구사항을 구체화하면, 주소 검증 로직 수정 필요 --- .../camp/woowak/lab/store/domain/StoreValidator.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/main/java/camp/woowak/lab/store/domain/StoreValidator.java b/src/main/java/camp/woowak/lab/store/domain/StoreValidator.java index bae9d4ca..c11bda14 100644 --- a/src/main/java/camp/woowak/lab/store/domain/StoreValidator.java +++ b/src/main/java/camp/woowak/lab/store/domain/StoreValidator.java @@ -17,6 +17,7 @@ public static void validate(final String name, final String address, final Integ final LocalDateTime startTime, final LocalDateTime endTime ) { validateName(name); + validateAddress(address); } private static void validateName(final String name) { @@ -26,4 +27,12 @@ private static void validateName(final String name) { throw new StoreException("가게 이름은 2글자 ~ 10글자 이어야합니다."); } + // TODO: 가게 위치 비즈니스 요구사항 구체화하면, 주소 검증 로직 수정 예정 + private static void validateAddress(final String address) { + if (Address.DEFAULT_DISTRICT.equals(address)) { + return; + } + throw new StoreException("가게 주소는 송파구만 가능합니다."); + } + } From 999e0f46ae5179b534b3958cada367cda6d1e7f6 Mon Sep 17 00:00:00 2001 From: june-777 Date: Sun, 11 Aug 2024 19:28:52 +0900 Subject: [PATCH 04/77] =?UTF-8?q?[feat]=20=EA=B0=80=EA=B2=8C=20=EC=B5=9C?= =?UTF-8?q?=EC=86=8C=20=EC=A3=BC=EB=AC=B8=20=EA=B8=88=EC=95=A1=20=EA=B2=80?= =?UTF-8?q?=EC=A6=9D=20=EA=B8=B0=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 5,000원 이상 - 1,000원 단위 --- .../woowak/lab/store/domain/StoreValidator.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/main/java/camp/woowak/lab/store/domain/StoreValidator.java b/src/main/java/camp/woowak/lab/store/domain/StoreValidator.java index c11bda14..1e34c4f8 100644 --- a/src/main/java/camp/woowak/lab/store/domain/StoreValidator.java +++ b/src/main/java/camp/woowak/lab/store/domain/StoreValidator.java @@ -18,6 +18,8 @@ public static void validate(final String name, final String address, final Integ ) { validateName(name); validateAddress(address); + validateMinOrderPrice(minOrderPrice); + validateUnitOrderPrice(minOrderPrice); } private static void validateName(final String name) { @@ -35,4 +37,16 @@ private static void validateAddress(final String address) { throw new StoreException("가게 주소는 송파구만 가능합니다."); } + private static void validateMinOrderPrice(final Integer minOrderPrice) { + if (minOrderPrice < MIN_ORDER_PRICE) { + throw new StoreException("최소 주문 금액은 5,000원 이상이어야 합니다."); + } + } + + private static void validateUnitOrderPrice(final Integer minOrderPrice) { + if (minOrderPrice % UNIT_OF_MIN_ORDER_PRICE != 0) { + throw new StoreException("최소 주문 금액은 1,000원 단위이어야 합니다."); + } + } + } From a962988f90e5ed72c704d92b2a19705fbfc42491 Mon Sep 17 00:00:00 2001 From: june-777 Date: Sun, 11 Aug 2024 19:29:41 +0900 Subject: [PATCH 05/77] =?UTF-8?q?[feat]=20=EA=B0=80=EA=B2=8C=20=EC=9D=B4?= =?UTF-8?q?=EC=9A=A9=20=EC=8B=9C=EA=B0=84=20=EA=B2=80=EC=A6=9D=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 가게 시작/종료 시간은 분 단위까지 가능 - 가게 시작 시간은 종료 시간보다 이전 --- .../lab/store/domain/StoreValidator.java | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/main/java/camp/woowak/lab/store/domain/StoreValidator.java b/src/main/java/camp/woowak/lab/store/domain/StoreValidator.java index 1e34c4f8..d791e5be 100644 --- a/src/main/java/camp/woowak/lab/store/domain/StoreValidator.java +++ b/src/main/java/camp/woowak/lab/store/domain/StoreValidator.java @@ -20,6 +20,7 @@ public static void validate(final String name, final String address, final Integ validateAddress(address); validateMinOrderPrice(minOrderPrice); validateUnitOrderPrice(minOrderPrice); + validateTime(startTime, endTime); } private static void validateName(final String name) { @@ -49,4 +50,28 @@ private static void validateUnitOrderPrice(final Integer minOrderPrice) { } } + private static void validateTime(final LocalDateTime startTime, + final LocalDateTime endTime + ) { + if (isInvalidStoreTimeUnit(startTime)) { + throw new StoreException("가게 시작 시간은 분 단위까지 가능합니다"); + } + + if (isInvalidStoreTimeUnit(endTime)) { + throw new StoreException("가게 종료 시간은 분 단위까지 가능합니다"); + } + + if (endTime.isBefore(startTime)) { + throw new StoreException("가게 시작 시간은 종료 시간보다 이전이어야 합니다"); + } + + if (startTime.isEqual(endTime)) { + throw new StoreException("가게 시작 시간과 종료 시간이 일치합니다"); + } + } + + private static boolean isInvalidStoreTimeUnit(final LocalDateTime target) { + return target.getSecond() != 0 || target.getNano() != 0; + } + } From 328e78f65c47efa6064ec2baeed30e809c14d4e1 Mon Sep 17 00:00:00 2001 From: june-777 Date: Sun, 11 Aug 2024 19:36:06 +0900 Subject: [PATCH 06/77] =?UTF-8?q?[feat]=20=EA=B0=80=EA=B2=8C=20=EC=A3=BC?= =?UTF-8?q?=EC=86=8C=20=EC=9E=84=EB=B2=A0=EB=94=94=EB=93=9C=20=ED=83=80?= =?UTF-8?q?=EC=9E=85=20=EC=A0=95=EC=9D=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 임베디드 타입 사용 이유 - 주소는 도시/구/상세주소 같은 정보들로 그룹핑 됨 - 현재는 프로토타입으로서 구 정보만 사용하지만, 가게 주소 비즈니스 요구사항이 구체화되면 다른 정보들도 활용할 여지가 있음 - 구체화가 완료되면, 엔티티로 분리할 것인지 논의 필요 --- .../camp/woowak/lab/store/domain/Store.java | 4 ++-- .../woowak/lab/store/domain/StoreAddress.java | 21 +++++++++++++++++++ .../lab/store/domain/StoreValidator.java | 2 +- 3 files changed, 24 insertions(+), 3 deletions(-) create mode 100644 src/main/java/camp/woowak/lab/store/domain/StoreAddress.java diff --git a/src/main/java/camp/woowak/lab/store/domain/Store.java b/src/main/java/camp/woowak/lab/store/domain/Store.java index d2a19ade..d67aeb3b 100644 --- a/src/main/java/camp/woowak/lab/store/domain/Store.java +++ b/src/main/java/camp/woowak/lab/store/domain/Store.java @@ -38,7 +38,7 @@ public class Store { // TODO: 위치 정보에 대한 요구사항 논의 후 수정 예정. // i.g) 송파구로 특정, 도시 정보로 특정 등 요구사항이 정의되어야 엔티티 설계를 진행할 수 있음 @Embedded - private Address address; + private StoreAddress storeAddress; @Column(nullable = false) private String phoneNumber; @@ -56,7 +56,7 @@ public Store(Vendor owner, StoreCategory storeCategory, String name, String addr this.owner = owner; this.storeCategory = storeCategory; this.name = name; - this.address = new Address(address); + this.storeAddress = new StoreAddress(address); this.phoneNumber = phoneNumber; this.minOrderPrice = minOrderPrice; this.storeTime = new StoreTime(startTime, endTime); diff --git a/src/main/java/camp/woowak/lab/store/domain/StoreAddress.java b/src/main/java/camp/woowak/lab/store/domain/StoreAddress.java new file mode 100644 index 00000000..2273aad2 --- /dev/null +++ b/src/main/java/camp/woowak/lab/store/domain/StoreAddress.java @@ -0,0 +1,21 @@ +package camp.woowak.lab.store.domain; + +import jakarta.persistence.Column; +import jakarta.persistence.Embeddable; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; + +@Embeddable +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class StoreAddress { + + public static final String DEFAULT_DISTRICT = "송파"; + + @Column(nullable = false) + private String district; + + public StoreAddress(final String district) { + this.district = district; + } + +} diff --git a/src/main/java/camp/woowak/lab/store/domain/StoreValidator.java b/src/main/java/camp/woowak/lab/store/domain/StoreValidator.java index d791e5be..ebcb133c 100644 --- a/src/main/java/camp/woowak/lab/store/domain/StoreValidator.java +++ b/src/main/java/camp/woowak/lab/store/domain/StoreValidator.java @@ -32,7 +32,7 @@ private static void validateName(final String name) { // TODO: 가게 위치 비즈니스 요구사항 구체화하면, 주소 검증 로직 수정 예정 private static void validateAddress(final String address) { - if (Address.DEFAULT_DISTRICT.equals(address)) { + if (StoreAddress.DEFAULT_DISTRICT.equals(address)) { return; } throw new StoreException("가게 주소는 송파구만 가능합니다."); From 48c2e7f21f5b82937d736b962cb4b1566f0de32e Mon Sep 17 00:00:00 2001 From: june-777 Date: Sun, 11 Aug 2024 19:37:39 +0900 Subject: [PATCH 07/77] =?UTF-8?q?[feat]=20=EA=B0=80=EA=B2=8C=20=EC=9D=B4?= =?UTF-8?q?=EC=9A=A9=20=EC=8B=9C=EA=B0=84=20=EC=9E=84=EB=B2=A0=EB=94=94?= =?UTF-8?q?=EB=93=9C=20=ED=83=80=EC=9E=85=20=EC=A0=95=EC=9D=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 임베디드 타입 사용 이유 - 이용 시간은 시작 시간/ 종료 시간 정보로 그룹핑 됨 - LocalDateTime 과 변수명만으로는 비즈니스 요구사항을 명시적으로 표현하기 제약이 있음 --- .../woowak/lab/store/domain/StoreTime.java | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 src/main/java/camp/woowak/lab/store/domain/StoreTime.java diff --git a/src/main/java/camp/woowak/lab/store/domain/StoreTime.java b/src/main/java/camp/woowak/lab/store/domain/StoreTime.java new file mode 100644 index 00000000..5640d8d8 --- /dev/null +++ b/src/main/java/camp/woowak/lab/store/domain/StoreTime.java @@ -0,0 +1,25 @@ +package camp.woowak.lab.store.domain; + +import java.time.LocalDateTime; + +import jakarta.persistence.Column; +import jakarta.persistence.Embeddable; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; + +@Embeddable +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class StoreTime { + + @Column(nullable = false) + private LocalDateTime startTime; + + @Column(nullable = false) + private LocalDateTime endTime; + + public StoreTime(final LocalDateTime startTime, final LocalDateTime endTime) { + this.startTime = startTime; + this.endTime = endTime; + } + +} From d3a40f450c1d34b85731fef65d6be338bcc1b852 Mon Sep 17 00:00:00 2001 From: june-777 Date: Sun, 11 Aug 2024 19:40:04 +0900 Subject: [PATCH 08/77] =?UTF-8?q?[feat]=20=EA=B0=80=EA=B2=8C=20=EC=B9=B4?= =?UTF-8?q?=ED=85=8C=EA=B3=A0=EB=A6=AC=20=EB=8F=84=EB=A9=94=EC=9D=B8=20?= =?UTF-8?q?=EC=97=94=ED=8B=B0=ED=8B=B0=20=EC=A0=95=EC=9D=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 도메인 엔티티로 분리한 이유: - 가게 카테고리는 DB 레벨에서 관리해야, 추후 카테고리를 추가/생성/삭제할 때 변경 이상에 대처가 용이할 것으로 판단 --- .../woowak/lab/store/domain/StoreCategory.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 src/main/java/camp/woowak/lab/store/domain/StoreCategory.java diff --git a/src/main/java/camp/woowak/lab/store/domain/StoreCategory.java b/src/main/java/camp/woowak/lab/store/domain/StoreCategory.java new file mode 100644 index 00000000..b30a20b0 --- /dev/null +++ b/src/main/java/camp/woowak/lab/store/domain/StoreCategory.java @@ -0,0 +1,17 @@ +package camp.woowak.lab.store.domain; + +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; + +@Entity +public class StoreCategory { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + private String name; + +} From 6df364cde2a090c4a9355d091e553efdd8130a7e Mon Sep 17 00:00:00 2001 From: june-777 Date: Sun, 11 Aug 2024 19:51:15 +0900 Subject: [PATCH 09/77] =?UTF-8?q?[feat]=20=EC=8B=9C=EA=B0=84=20=EC=A0=95?= =?UTF-8?q?=EB=B3=B4=EB=A5=BC=20=EC=A0=9C=EA=B3=B5=ED=95=98=EB=8A=94=20Dat?= =?UTF-8?q?eTimeProvider=20=EC=9D=B8=ED=84=B0=ED=8E=98=EC=9D=B4=EC=8A=A4?= =?UTF-8?q?=20=EC=A0=95=EC=9D=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 인터페이스 설계 이유: 날짜 API 를 직접 참조함으로서 테스트하기 어려워지는 코드를 예방하기 위함 --- .../lab/infra/date/DateTimeProvider.java | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 src/main/java/camp/woowak/lab/infra/date/DateTimeProvider.java diff --git a/src/main/java/camp/woowak/lab/infra/date/DateTimeProvider.java b/src/main/java/camp/woowak/lab/infra/date/DateTimeProvider.java new file mode 100644 index 00000000..abefd7b3 --- /dev/null +++ b/src/main/java/camp/woowak/lab/infra/date/DateTimeProvider.java @@ -0,0 +1,20 @@ +package camp.woowak.lab.infra.date; + +import java.time.LocalDateTime; + +/** + *

인터페이스 도입 배경

+ * 메서드 내부 구현에 LocalDateTime.now 직접 사용하는 등 제어할 수 없는 영역을 인터페이스로 분리하여 제어 가능하도록 함
+ * 날짜로 인해 테스트 어려운 코드를 테스트 용이하도록 하기 위함 + * + *

Production Level

+ * 구현체: CurrentDateTime + * + *

Test Level

+ * 구현체: FixedDateTime + */ +public interface DateTimeProvider { + + LocalDateTime now(); + +} \ No newline at end of file From 4a7be13d35b6ddb2774e1af9894e4df3dd849be3 Mon Sep 17 00:00:00 2001 From: june-777 Date: Sun, 11 Aug 2024 20:04:29 +0900 Subject: [PATCH 10/77] =?UTF-8?q?[feat]=20=EA=B3=A0=EC=A0=95=20=EC=8B=9C?= =?UTF-8?q?=EA=B0=84=EC=9D=84=20=EB=B0=98=ED=99=98=ED=95=98=EB=8A=94=20Dat?= =?UTF-8?q?eTimeProvider=20=ED=85=8C=EC=8A=A4=ED=8A=B8=EC=9A=A9=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84=EC=B2=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 시간 관련 로직을 테스트할 때 사용 사용 방법은 javadocs 로 샘플 코드 기재 --- .../woowak/lab/infra/time/FixedDateTime.java | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 src/test/java/camp/woowak/lab/infra/time/FixedDateTime.java diff --git a/src/test/java/camp/woowak/lab/infra/time/FixedDateTime.java b/src/test/java/camp/woowak/lab/infra/time/FixedDateTime.java new file mode 100644 index 00000000..8a7f9125 --- /dev/null +++ b/src/test/java/camp/woowak/lab/infra/time/FixedDateTime.java @@ -0,0 +1,38 @@ +package camp.woowak.lab.infra.time; + +import java.time.LocalDateTime; + +import camp.woowak.lab.infra.date.DateTimeProvider; + +/** + *

Sample Code

+ *

with Lambda

+ *
+ * {@code
+ * DateTimeProvider fixedTimeProvider = () -> LocalDateTime.of(2024, 8, 24, 1, 0, 0);
+ * LocalDateTime fixedTime = fixedTimeProvider.now();
+ * }
+ * 
+ * + *

with Constructor

+ *
+ * {@code
+ * DateTimeProvider fixedTimeProvider = new FixedDateTime(2024, 8, 24, 1, 0, 0);
+ * LocalDateTime fixedTime = fixedTimeProvider.now();
+ * }
+ * 
+ */ +public class FixedDateTime implements DateTimeProvider { + + private final LocalDateTime fixedDateTime; + + public FixedDateTime(int year, int month, int day, int hour, int minute, int second) { + fixedDateTime = LocalDateTime.of(year, month, day, hour, minute, second); + } + + @Override + public LocalDateTime now() { + return fixedDateTime; + } + +} From 835ad624ed99c06965f559fcbfdb0132cb04057f Mon Sep 17 00:00:00 2001 From: june-777 Date: Sun, 11 Aug 2024 20:04:51 +0900 Subject: [PATCH 11/77] =?UTF-8?q?[feat]=20=ED=98=84=EC=9E=AC=20=EC=8B=9C?= =?UTF-8?q?=EA=B0=84=EC=9D=84=20=EB=B0=98=ED=99=98=ED=95=98=EB=8A=94=20Dat?= =?UTF-8?q?eTimeProvider=20=ED=94=84=EB=A1=9C=EB=8D=95=EC=85=98=EC=9A=A9?= =?UTF-8?q?=20=EA=B5=AC=ED=98=84=EC=B2=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../camp/woowak/lab/infra/date/CurrentDateTime.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 src/main/java/camp/woowak/lab/infra/date/CurrentDateTime.java diff --git a/src/main/java/camp/woowak/lab/infra/date/CurrentDateTime.java b/src/main/java/camp/woowak/lab/infra/date/CurrentDateTime.java new file mode 100644 index 00000000..f720aec2 --- /dev/null +++ b/src/main/java/camp/woowak/lab/infra/date/CurrentDateTime.java @@ -0,0 +1,12 @@ +package camp.woowak.lab.infra.date; + +import java.time.LocalDateTime; + +public class CurrentDateTime implements DateTimeProvider { + + @Override + public LocalDateTime now() { + return LocalDateTime.now(); + } + +} From fe3110fff21400c35dd59831a2d7c376191540f7 Mon Sep 17 00:00:00 2001 From: june-777 Date: Sun, 11 Aug 2024 20:05:32 +0900 Subject: [PATCH 12/77] =?UTF-8?q?[feat]=20DateTimeProvider=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84=EC=B2=B4=EC=9D=B8=20CurrentDateTime=20=EB=A5=BC=20Bea?= =?UTF-8?q?n=20=EA=B0=9D=EC=B2=B4=EB=A1=9C=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lab/infra/config/InfraConfiguration.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 src/main/java/camp/woowak/lab/infra/config/InfraConfiguration.java diff --git a/src/main/java/camp/woowak/lab/infra/config/InfraConfiguration.java b/src/main/java/camp/woowak/lab/infra/config/InfraConfiguration.java new file mode 100644 index 00000000..781cd074 --- /dev/null +++ b/src/main/java/camp/woowak/lab/infra/config/InfraConfiguration.java @@ -0,0 +1,17 @@ +package camp.woowak.lab.infra.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import camp.woowak.lab.infra.date.CurrentDateTime; +import camp.woowak.lab.infra.date.DateTimeProvider; + +@Configuration +public class InfraConfiguration { + + @Bean + public DateTimeProvider dateTimeProvider() { + return new CurrentDateTime(); + } + +} From 1e8885a8836861fe54075a54904f337873f2c381 Mon Sep 17 00:00:00 2001 From: june-777 Date: Sun, 11 Aug 2024 20:24:07 +0900 Subject: [PATCH 13/77] =?UTF-8?q?[test]=20Store=20=EB=8F=84=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20=EA=B0=9D=EC=B2=B4=20=EC=83=9D=EC=84=B1=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20-=20=EA=B0=80=EA=B2=8C=20=EC=B5=9C?= =?UTF-8?q?=EC=86=8C=20=EC=A3=BC=EB=AC=B8=20=EA=B0=80=EA=B2=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../woowak/lab/store/domain/StoreTest.java | 91 +++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 src/test/java/camp/woowak/lab/store/domain/StoreTest.java diff --git a/src/test/java/camp/woowak/lab/store/domain/StoreTest.java b/src/test/java/camp/woowak/lab/store/domain/StoreTest.java new file mode 100644 index 00000000..6ea64cec --- /dev/null +++ b/src/test/java/camp/woowak/lab/store/domain/StoreTest.java @@ -0,0 +1,91 @@ +package camp.woowak.lab.store.domain; + +import static org.assertj.core.api.Assertions.*; + +import java.time.LocalDateTime; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import camp.woowak.lab.infra.date.DateTimeProvider; +import camp.woowak.lab.store.exception.StoreException; + +class StoreTest { + + @Nested + @DisplayName("Store 생성은") + class StoreValidateTest { + + DateTimeProvider fixedStartTime = () -> LocalDateTime.of(2024, 8, 24, 1, 0, 0); + DateTimeProvider fixedEndTime = () -> LocalDateTime.of(2024, 8, 24, 5, 0, 0); + + LocalDateTime validStartTimeFixture = fixedStartTime.now(); + LocalDateTime validEndTimeFixture = fixedEndTime.now(); + + String validNameFixture = "3K1K 가게"; + + String validAddressFixture = StoreAddress.DEFAULT_DISTRICT; + + Integer validMinOrderPriceFixture = 5000; + + @Nested + @DisplayName("가게 최소 주문 가격이") + class StoreMinOrderPrice { + + @Test + @DisplayName("[Success] 5,000원 이상 가능하다") + void validMinOrderPrice() { + // given + int validMinOrderPrice = 5000; + + // when & then + assertThatCode(() -> new Store(null, null, validNameFixture, validAddressFixture, null, + validMinOrderPrice, + validStartTimeFixture, validEndTimeFixture)) + .doesNotThrowAnyException(); + } + + @Test + @DisplayName("[Exception] 5,000원 미만이면 StoreException 이 발생한다") + void lessThanMinOrderPrice() { + // given + int lessThanMinOrderPrice = 4999; + + // when & then + assertThatThrownBy(() -> new Store(null, null, validNameFixture, validAddressFixture, null, + lessThanMinOrderPrice, + validStartTimeFixture, validEndTimeFixture)) + .isInstanceOf(StoreException.class); + } + + @Test + @DisplayName("[Success] 1,000원 단위로 가능하다") + void validUnitOrderPrice() { + // given + int validMinOrderPrice = 10000; + + // when & then + assertThatCode(() -> new Store(null, null, validNameFixture, validAddressFixture, null, + validMinOrderPrice, + validStartTimeFixture, validEndTimeFixture)) + .doesNotThrowAnyException(); + } + + @Test + @DisplayName("[Exception] 1,000원 단위가 아니면 StoreException 이 발생한다") + void inValidUnitOrderPrice() { + // given + int inValidUnitOrderPrice = 5001; + + // when & then + assertThatThrownBy(() -> new Store(null, null, validNameFixture, validAddressFixture, null, + inValidUnitOrderPrice, + validStartTimeFixture, validEndTimeFixture)) + .isInstanceOf(StoreException.class); + } + } + + } + +} \ No newline at end of file From aa47da4e2b494512a89399d0685e83293a0f32a5 Mon Sep 17 00:00:00 2001 From: june-777 Date: Sun, 11 Aug 2024 20:24:48 +0900 Subject: [PATCH 14/77] =?UTF-8?q?[test]=20Store=20=EB=8F=84=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20=EA=B0=9D=EC=B2=B4=20=EC=83=9D=EC=84=B1=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20-=20=EA=B0=80=EA=B2=8C=20=EC=9D=B4?= =?UTF-8?q?=EC=9A=A9=20=EC=8B=9C=EA=B0=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../woowak/lab/store/domain/StoreTest.java | 113 ++++++++++++++++++ 1 file changed, 113 insertions(+) diff --git a/src/test/java/camp/woowak/lab/store/domain/StoreTest.java b/src/test/java/camp/woowak/lab/store/domain/StoreTest.java index 6ea64cec..32e84a54 100644 --- a/src/test/java/camp/woowak/lab/store/domain/StoreTest.java +++ b/src/test/java/camp/woowak/lab/store/domain/StoreTest.java @@ -86,6 +86,119 @@ void inValidUnitOrderPrice() { } } + @Nested + @DisplayName("가게 이용 시간이") + class StoreTime { + + @Test + @DisplayName("[Success] 시작 시간이 종료 시간보다 이전이다") + void storeStartTimeBeforeThanEndTime() { + // given + LocalDateTime validStartTime = validStartTimeFixture; + LocalDateTime validEndTime = validEndTimeFixture; + + // when & then + assertThatCode( + () -> new Store(null, null, validNameFixture, validAddressFixture, null, validMinOrderPriceFixture, + validStartTime, validEndTime)) + .doesNotThrowAnyException(); + } + + @Test + @DisplayName("[Exception] 종료 시간이 시작 시간과 같으면 StoreException 이 발생한다") + void endTimeSameWithStartTime() { + // given + LocalDateTime endTimeSameWithStartTime = fixedStartTime.now(); + + // when & then + assertThatThrownBy( + () -> new Store(null, null, validNameFixture, validAddressFixture, null, validMinOrderPriceFixture, + validStartTimeFixture, endTimeSameWithStartTime)) + .isInstanceOf(StoreException.class); + } + + @Test + @DisplayName("[Exception] 종료 시간이 시작 시간 이전이면 StoreException 이 발생한다") + void endTimeBeforeThanStartTime() { + // given + LocalDateTime endTimeBeforeThanStartTime = validStartTimeFixture.minusMinutes(1); + + // when & then + assertThatThrownBy( + () -> new Store(null, null, validNameFixture, validAddressFixture, null, validMinOrderPriceFixture, + validStartTimeFixture, endTimeBeforeThanStartTime)) + .isInstanceOf(StoreException.class); + } + + @Test + @DisplayName("[Success] 시작 시간과 종료 시간의 단위는 분(m) 단위 까지 가능하다") + void validStartTimeUnit() { + // given + LocalDateTime validStartTimeUnitMinute = validStartTimeFixture; + LocalDateTime validEndTimeUnitMinute = validEndTimeFixture; + + // when & then + assertThatCode( + () -> new Store(null, null, validNameFixture, validAddressFixture, null, validMinOrderPriceFixture, + validStartTimeUnitMinute, validEndTimeUnitMinute)) + .doesNotThrowAnyException(); + } + + @Test + @DisplayName("[Exception] 시작 시간에 초(s) 단위가 포함되면 StoreException 이 발생한다") + void startTimeWithSeconds() { + // given + DateTimeProvider inValidUnitDateTimeProvider = () -> LocalDateTime.of(2024, 8, 24, 10, 10, 1); + LocalDateTime startTimeWithSeconds = inValidUnitDateTimeProvider.now(); + + // when & then + assertThatThrownBy( + () -> new Store(null, null, validNameFixture, validAddressFixture, null, validMinOrderPriceFixture, + startTimeWithSeconds, validEndTimeFixture)) + .isInstanceOf(StoreException.class); + } + + @Test + @DisplayName("[Exception] 시작 시간에 나노초(ms) 단위가 포함되면 StoreException 이 발생한다") + void startTimeWithNanoSeconds() { + // given + DateTimeProvider inValidUnitDateTimeProvider = () -> LocalDateTime.of(2024, 8, 24, 10, 0, 0, 1); + LocalDateTime startTimeWithNanoSeconds = inValidUnitDateTimeProvider.now(); + + // when & then + assertThatThrownBy(() -> new Store(null, null, validNameFixture, validAddressFixture, null, 5000, + startTimeWithNanoSeconds, validEndTimeFixture)) + .isInstanceOf(StoreException.class); + } + + @Test + @DisplayName("[Exception] 종료 시간에 초(s) 단위가 포함되면 StoreException 이 발생한다") + void endTimeWithSeconds() { + // given + DateTimeProvider inValidUnitDateTimeProvider = () -> LocalDateTime.of(2024, 8, 24, 10, 30, 1); + LocalDateTime endTimeWithSeconds = inValidUnitDateTimeProvider.now(); + + // when & then + assertThatThrownBy(() -> new Store(null, null, validNameFixture, validAddressFixture, null, 5000, + validStartTimeFixture, endTimeWithSeconds)) + .isInstanceOf(StoreException.class); + } + + @Test + @DisplayName("[Exception] 종료 시간에 나노초(ms) 단위가 포함되면 StoreException 이 발생한다") + void endTimeWithNanoSeconds() { + // given + DateTimeProvider inValidUnitDateTimeProvider = () -> LocalDateTime.of(2024, 8, 24, 10, 30, 0, 1); + LocalDateTime endTimeWithNanoSeconds = inValidUnitDateTimeProvider.now(); + + // when & then + assertThatThrownBy(() -> new Store(null, null, validNameFixture, validAddressFixture, null, 5000, + validStartTimeFixture, endTimeWithNanoSeconds)) + .isInstanceOf(StoreException.class); + } + + } + } } \ No newline at end of file From 7791f9ae7e046a0b1b38222acb5c64e074efa0a6 Mon Sep 17 00:00:00 2001 From: june-777 Date: Sun, 11 Aug 2024 20:25:10 +0900 Subject: [PATCH 15/77] =?UTF-8?q?[test]=20Store=20=EB=8F=84=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20=EA=B0=9D=EC=B2=B4=20=EC=83=9D=EC=84=B1=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20-=20=EA=B0=80=EA=B2=8C=20=EC=9D=B4?= =?UTF-8?q?=EB=A6=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../woowak/lab/store/domain/StoreTest.java | 76 +++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/src/test/java/camp/woowak/lab/store/domain/StoreTest.java b/src/test/java/camp/woowak/lab/store/domain/StoreTest.java index 32e84a54..b6391d64 100644 --- a/src/test/java/camp/woowak/lab/store/domain/StoreTest.java +++ b/src/test/java/camp/woowak/lab/store/domain/StoreTest.java @@ -199,6 +199,82 @@ void endTimeWithNanoSeconds() { } + @Nested + @DisplayName("가게 이름이") + class StoreName { + + @Test + @DisplayName("[Success] 2자 ~ 10자까지 가능하다") + void validStoreName() { + // given + String lengthValidStoreName = validNameFixture; + + // when & then + assertThatCode(() -> new Store(null, null, lengthValidStoreName, validAddressFixture, null, + validMinOrderPriceFixture, + validStartTimeFixture, validEndTimeFixture)) + .doesNotThrowAnyException(); + } + + @Test + @DisplayName("[Exception] 2자 미만이면 StoreException 이 발생한다") + void lessThanMinLengthName() { + // given + String lessThanMinLengthName = "헤"; + + // when & then + assertThatThrownBy(() -> new Store(null, null, lessThanMinLengthName, validAddressFixture, null, + validMinOrderPriceFixture, + validStartTimeFixture, validEndTimeFixture)) + .isInstanceOf(StoreException.class); + } + + @Test + @DisplayName("[Exception] 10자 초과면 StoreException 이 발생한다") + void greaterThanMaxLengthName() { + // given + String greaterThanMaxLengthName = "123456789가게"; + + // when & then + assertThatThrownBy( + () -> new Store(null, null, greaterThanMaxLengthName, validAddressFixture, null, + validMinOrderPriceFixture, + validStartTimeFixture, validEndTimeFixture)) + .isInstanceOf(StoreException.class); + } + + } + + @Nested + @DisplayName("가게 주소가") + class StoreAddressTest { + + @Test + @DisplayName("[Success] 송파구만 가능하다") + void onlySongPa() { + // given + String validAddress = "송파"; + // when & then + assertThatCode( + () -> new Store(null, null, validNameFixture, validAddress, null, validMinOrderPriceFixture, + validStartTimeFixture, validEndTimeFixture)) + .doesNotThrowAnyException(); + } + + @Test + @DisplayName("[Exception] 송파구가 아닌 주소는 StoreException 이 발생한다") + void notSongPa() { + // given + String validAddress = "강남"; + // when & then + assertThatThrownBy( + () -> new Store(null, null, validNameFixture, validAddress, null, validMinOrderPriceFixture, + validStartTimeFixture, validEndTimeFixture)) + .isInstanceOf(StoreException.class); + } + + } + } } \ No newline at end of file From 29996058157503388a07c34555d4c92eaa8d4339 Mon Sep 17 00:00:00 2001 From: june-777 Date: Sun, 11 Aug 2024 20:27:21 +0900 Subject: [PATCH 16/77] =?UTF-8?q?[feat]=20Store=20(=EA=B0=80=EA=B2=8C)=20?= =?UTF-8?q?=EB=8F=84=EB=A9=94=EC=9D=B8=20=EA=B4=80=EB=A0=A8=20=EC=BB=A4?= =?UTF-8?q?=EC=8A=A4=ED=85=80=20=EC=98=88=EC=99=B8=20=EC=A0=95=EC=9D=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Store 와 관련된 예외임을 명시적으로 나타내고자 함 IllegalArgumentException 등 Java 에서 제공하는 기본 예외는 예외의 명시성이 떨어진다 판단 --- .../camp/woowak/lab/store/exception/StoreException.java | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 src/main/java/camp/woowak/lab/store/exception/StoreException.java diff --git a/src/main/java/camp/woowak/lab/store/exception/StoreException.java b/src/main/java/camp/woowak/lab/store/exception/StoreException.java new file mode 100644 index 00000000..33cd1642 --- /dev/null +++ b/src/main/java/camp/woowak/lab/store/exception/StoreException.java @@ -0,0 +1,9 @@ +package camp.woowak.lab.store.exception; + +public class StoreException extends RuntimeException { + + public StoreException(String message) { + super(message); + } + +} From 6a4f101d8f82596f67118be2d82920f2f69203a3 Mon Sep 17 00:00:00 2001 From: june-777 Date: Sun, 11 Aug 2024 21:56:15 +0900 Subject: [PATCH 17/77] =?UTF-8?q?[feat]=20=EA=B0=80=EA=B2=8C=20=EC=B9=B4?= =?UTF-8?q?=ED=85=8C=EA=B3=A0=EB=A6=AC=20=EC=83=9D=EC=84=B1=EC=9E=90=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 기본 생성자는 애노테이션 사용 및 protected 접근 제어자로 설정 --- .../java/camp/woowak/lab/store/domain/StoreCategory.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/java/camp/woowak/lab/store/domain/StoreCategory.java b/src/main/java/camp/woowak/lab/store/domain/StoreCategory.java index b30a20b0..60558407 100644 --- a/src/main/java/camp/woowak/lab/store/domain/StoreCategory.java +++ b/src/main/java/camp/woowak/lab/store/domain/StoreCategory.java @@ -4,8 +4,11 @@ import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; @Entity +@NoArgsConstructor(access = AccessLevel.PROTECTED) public class StoreCategory { @Id @@ -14,4 +17,8 @@ public class StoreCategory { private String name; + public StoreCategory(String name) { + this.name = name; + } + } From c7667394108c16bc9170a25e58baab3f4860e7a5 Mon Sep 17 00:00:00 2001 From: june-777 Date: Sun, 11 Aug 2024 21:56:48 +0900 Subject: [PATCH 18/77] =?UTF-8?q?[feat]=20StoreRepository=20JPA=20?= =?UTF-8?q?=EC=9D=B8=ED=84=B0=ED=8E=98=EC=9D=B4=EC=8A=A4=20=EC=A0=95?= =?UTF-8?q?=EC=9D=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../camp/woowak/lab/store/repository/StoreRepository.java | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 src/main/java/camp/woowak/lab/store/repository/StoreRepository.java diff --git a/src/main/java/camp/woowak/lab/store/repository/StoreRepository.java b/src/main/java/camp/woowak/lab/store/repository/StoreRepository.java new file mode 100644 index 00000000..a4f98667 --- /dev/null +++ b/src/main/java/camp/woowak/lab/store/repository/StoreRepository.java @@ -0,0 +1,8 @@ +package camp.woowak.lab.store.repository; + +import org.springframework.data.jpa.repository.JpaRepository; + +import camp.woowak.lab.store.domain.Store; + +public interface StoreRepository extends JpaRepository { +} From bc5b95438ba6acd67bd6300ffbf5cc13c181bebf Mon Sep 17 00:00:00 2001 From: june-777 Date: Sun, 11 Aug 2024 22:01:29 +0900 Subject: [PATCH 19/77] =?UTF-8?q?[test]=20StoreRepository=20=EA=B0=80?= =?UTF-8?q?=EA=B2=8C=20=EC=A0=80=EC=9E=A5=20=EA=B8=B0=EB=8A=A5=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - repository 단위 테스트는 @DataJpaTest 로 최소한의 Bean 만 주입하여 사용 - @SpringBootTest 는 모든 Bean 을 로드하기 때문에 테스트가 무거워짐 --- .../store/repository/StoreRepositoryTest.java | 88 +++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 src/test/java/camp/woowak/lab/store/repository/StoreRepositoryTest.java diff --git a/src/test/java/camp/woowak/lab/store/repository/StoreRepositoryTest.java b/src/test/java/camp/woowak/lab/store/repository/StoreRepositoryTest.java new file mode 100644 index 00000000..f04cc524 --- /dev/null +++ b/src/test/java/camp/woowak/lab/store/repository/StoreRepositoryTest.java @@ -0,0 +1,88 @@ +package camp.woowak.lab.store.repository; + +import java.time.LocalDateTime; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.dao.InvalidDataAccessApiUsageException; + +import camp.woowak.lab.infra.date.DateTimeProvider; +import camp.woowak.lab.store.domain.Store; +import camp.woowak.lab.store.domain.StoreAddress; +import camp.woowak.lab.store.domain.StoreCategory; +import camp.woowak.lab.vendor.domain.Vendor; +import camp.woowak.lab.vendor.repository.VendorRepository; + +@DataJpaTest +class StoreRepositoryTest { + + @Autowired + private StoreRepository storeRepository; + + @Autowired + private VendorRepository vendorRepository; + + @Autowired + private StoreCategoryRepository storeCategoryRepository; + + DateTimeProvider fixedStartTime = () -> LocalDateTime.of(2024, 8, 24, 1, 0, 0); + DateTimeProvider fixedEndTime = () -> LocalDateTime.of(2024, 8, 24, 5, 0, 0); + + LocalDateTime validStartTimeFixture = fixedStartTime.now(); + LocalDateTime validEndTimeFixture = fixedEndTime.now(); + + String validNameFixture = "3K1K 가게"; + String validAddressFixture = StoreAddress.DEFAULT_DISTRICT; + String validPhoneNumberFixture = "02-0000-0000"; + Integer validMinOrderPriceFixture = 5000; + + @Test + @DisplayName("[Success] 가게 저장 성공") + void successfulSaveStore() { + // given + Vendor vendor = new Vendor(); + vendorRepository.saveAndFlush(vendor); + + StoreCategory storeCategory = new StoreCategory("한식"); + storeCategoryRepository.saveAndFlush(storeCategory); + + Store store = createStore(vendor, storeCategory); + + // when & then + Assertions.assertThatCode(() -> storeRepository.save(store)) + .doesNotThrowAnyException(); + } + + @Test + @DisplayName("[Exception] 참조중인 엔티티가 저장되지 않았고, Not Null 제약조건이면 InvalidDataAccessApiUsageException - Not-null property 가 발생한다") + void test() { + // given + Vendor notSavedVendor = new Vendor(); + + StoreCategory storeCategory = new StoreCategory("한식"); + storeCategoryRepository.saveAndFlush(storeCategory); + + // when + Store store = createStore(notSavedVendor, storeCategory); + + // then + Assertions.assertThatThrownBy(() -> storeRepository.saveAndFlush(store)) + .isInstanceOf(InvalidDataAccessApiUsageException.class); + } + + private Store createStore(Vendor vendor, StoreCategory storeCategory) { + return new Store(vendor, + storeCategory, + validNameFixture, + validAddressFixture, + validPhoneNumberFixture, + validMinOrderPriceFixture, + validStartTimeFixture, + validEndTimeFixture + ); + } + +} \ No newline at end of file From bdef77a953c2e2b96ba0c19c93982b05eee65e15 Mon Sep 17 00:00:00 2001 From: june-777 Date: Sun, 11 Aug 2024 22:02:37 +0900 Subject: [PATCH 20/77] =?UTF-8?q?[feat]=20StoreCategoryRepository=20JPA=20?= =?UTF-8?q?=EC=9D=B8=ED=84=B0=ED=8E=98=EC=9D=B4=EC=8A=A4=20=EC=A0=95?= =?UTF-8?q?=EC=9D=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 가게 카테고리 이름으로 조회하는 시그니쳐 추가 --- .../store/repository/StoreCategoryRepository.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 src/main/java/camp/woowak/lab/store/repository/StoreCategoryRepository.java diff --git a/src/main/java/camp/woowak/lab/store/repository/StoreCategoryRepository.java b/src/main/java/camp/woowak/lab/store/repository/StoreCategoryRepository.java new file mode 100644 index 00000000..5988f8b5 --- /dev/null +++ b/src/main/java/camp/woowak/lab/store/repository/StoreCategoryRepository.java @@ -0,0 +1,13 @@ +package camp.woowak.lab.store.repository; + +import java.util.Optional; + +import org.springframework.data.jpa.repository.JpaRepository; + +import camp.woowak.lab.store.domain.StoreCategory; + +public interface StoreCategoryRepository extends JpaRepository { + + Optional findByName(String name); + +} From 3575f1dae20569f648ae0cb5a146f0dcb0168dbd Mon Sep 17 00:00:00 2001 From: june-777 Date: Sun, 11 Aug 2024 22:03:08 +0900 Subject: [PATCH 21/77] =?UTF-8?q?[test]=20=EA=B0=80=EA=B2=8C=20=EC=B9=B4?= =?UTF-8?q?=ED=85=8C=EA=B3=A0=EB=A6=AC=20=EC=9D=B4=EB=A6=84=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EC=A1=B0=ED=9A=8C=ED=95=98=EB=8A=94=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../StoreCategoryRepositoryTest.java | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 src/test/java/camp/woowak/lab/store/repository/StoreCategoryRepositoryTest.java diff --git a/src/test/java/camp/woowak/lab/store/repository/StoreCategoryRepositoryTest.java b/src/test/java/camp/woowak/lab/store/repository/StoreCategoryRepositoryTest.java new file mode 100644 index 00000000..1231aa86 --- /dev/null +++ b/src/test/java/camp/woowak/lab/store/repository/StoreCategoryRepositoryTest.java @@ -0,0 +1,55 @@ +package camp.woowak.lab.store.repository; + +import static org.assertj.core.api.Assertions.*; + +import java.util.Optional; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; + +import camp.woowak.lab.store.domain.StoreCategory; + +@DataJpaTest +class StoreCategoryRepositoryTest { + + @Autowired + StoreCategoryRepository storeCategoryRepository; + + @Nested + @DisplayName("가게 카테고리를 이름으로 조회하는 기능은") + class FindByNameTest { + + @Test + @DisplayName("[Success] 존재하는 가게 카테고리로 조회하면 Optional 에 가게 카테고리가 있다") + void existStoreCategory() { + // given + String storeCategoryName = "양식"; + StoreCategory storeCategory = new StoreCategory(storeCategoryName); + storeCategoryRepository.saveAndFlush(storeCategory); + + // when + Optional findResult = storeCategoryRepository.findByName(storeCategoryName); + + // then + assertThat(findResult) + .isPresent() + .containsSame(storeCategory); + } + + @Test + @DisplayName("[Exception] 없는 가게 카테고리로 조회하면 빈 값을 반환한다") + void notExistStoreCategory() { + // given + String notExistStoreCategoryName = "없는가게카테고리"; + + // when & then + assertThat(storeCategoryRepository.findByName(notExistStoreCategoryName)) + .isEmpty(); + } + + } + +} \ No newline at end of file From df6a123e904f505e908127aca49a208d34f76f67 Mon Sep 17 00:00:00 2001 From: june-777 Date: Sun, 11 Aug 2024 22:04:23 +0900 Subject: [PATCH 22/77] =?UTF-8?q?[feat]=20VendorRepository=20JPA=20?= =?UTF-8?q?=EC=9D=B8=ED=84=B0=ED=8E=98=EC=9D=B4=EC=8A=A4=20=EC=A0=95?= =?UTF-8?q?=EC=9D=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - StoreRepository 단위 테스트를 위해 정의함 - Store 엔티티를 저장할 때, 참조중인 Vendor(Not Null) 를 저장해야 Not-Null Property Exception 이 발생하지 않음 --- .../woowak/lab/vendor/repository/VendorRepository.java | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 src/main/java/camp/woowak/lab/vendor/repository/VendorRepository.java diff --git a/src/main/java/camp/woowak/lab/vendor/repository/VendorRepository.java b/src/main/java/camp/woowak/lab/vendor/repository/VendorRepository.java new file mode 100644 index 00000000..1d1d6f51 --- /dev/null +++ b/src/main/java/camp/woowak/lab/vendor/repository/VendorRepository.java @@ -0,0 +1,8 @@ +package camp.woowak.lab.vendor.repository; + +import org.springframework.data.jpa.repository.JpaRepository; + +import camp.woowak.lab.vendor.domain.Vendor; + +public interface VendorRepository extends JpaRepository { +} \ No newline at end of file From 3f2609ee116c47e9d570ad442dc506d083f0ee5f Mon Sep 17 00:00:00 2001 From: june-777 Date: Sun, 11 Aug 2024 22:12:56 +0900 Subject: [PATCH 23/77] =?UTF-8?q?[feat]=20=EA=B0=80=EA=B2=8C=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=EC=9D=84=20=EB=8B=B4=EB=8B=B9=ED=95=98=EB=8A=94=20?= =?UTF-8?q?=EC=84=9C=EB=B9=84=EC=8A=A4=20=ED=81=B4=EB=9E=98=EC=8A=A4=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 발생가능한 RunTimeException 은 javadocs 로 명시 --- .../service/StoreRegistrationService.java | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 src/main/java/camp/woowak/lab/store/service/StoreRegistrationService.java diff --git a/src/main/java/camp/woowak/lab/store/service/StoreRegistrationService.java b/src/main/java/camp/woowak/lab/store/service/StoreRegistrationService.java new file mode 100644 index 00000000..3b15d264 --- /dev/null +++ b/src/main/java/camp/woowak/lab/store/service/StoreRegistrationService.java @@ -0,0 +1,46 @@ +package camp.woowak.lab.store.service; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import camp.woowak.lab.store.domain.Store; +import camp.woowak.lab.store.domain.StoreCategory; +import camp.woowak.lab.store.exception.StoreException; +import camp.woowak.lab.store.repository.StoreCategoryRepository; +import camp.woowak.lab.store.repository.StoreRepository; +import camp.woowak.lab.vendor.domain.Vendor; +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +public class StoreRegistrationService { + + private final StoreRepository storeRepository; + private final StoreCategoryRepository storeCategoryRepository; + + /** + * @throws StoreException Store 객체 검증 실패, 존재하지 않는 이름의 가게 카테고리 + */ + @Transactional + public void storeRegistration(final Vendor vendor, final StoreRegistrationRequest request) { + final StoreCategory storeCategory = findStoreCategoryByName(request.storeCategoryName()); + final Store store = createStore(vendor, storeCategory, request); + + storeRepository.save(store); + } + + private static Store createStore(Vendor vendor, StoreCategory storeCategory, StoreRegistrationRequest request) { + return new Store(vendor, storeCategory, request.storeName(), + request.storeAddress(), + request.storePhoneNumber(), + request.storeMinOrderPrice(), + request.storeStarTime(), + request.storeEndTime()); + } + + private StoreCategory findStoreCategoryByName(final String name) { + return storeCategoryRepository.findByName(name) + .orElseThrow(() -> new StoreException("존재하지 않는 가게 카테고리입니다.")); + } + +} From 3224a6d95a7bf51de6837067c1a197ad0b19daa2 Mon Sep 17 00:00:00 2001 From: june-777 Date: Sun, 11 Aug 2024 22:14:52 +0900 Subject: [PATCH 24/77] =?UTF-8?q?[feat]=20=EA=B0=80=EA=B2=8C=20=EB=93=B1?= =?UTF-8?q?=EB=A1=9D=20=EC=9A=94=EC=B2=AD=20DTO?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Not Null, 빈값, 빈값 포함한 공백 에 대한 입력 검증은 Bean Validation 으로 검증함 --- .../service/StoreRegistrationRequest.java | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 src/main/java/camp/woowak/lab/store/service/StoreRegistrationRequest.java diff --git a/src/main/java/camp/woowak/lab/store/service/StoreRegistrationRequest.java b/src/main/java/camp/woowak/lab/store/service/StoreRegistrationRequest.java new file mode 100644 index 00000000..6b2d1559 --- /dev/null +++ b/src/main/java/camp/woowak/lab/store/service/StoreRegistrationRequest.java @@ -0,0 +1,31 @@ +package camp.woowak.lab.store.service; + +import java.time.LocalDateTime; + +import jakarta.validation.constraints.NotBlank; + +public record StoreRegistrationRequest( + + @NotBlank + String storeName, + + @NotBlank + String storeAddress, + + @NotBlank + String storePhoneNumber, + + @NotBlank + String storeCategoryName, + + @NotBlank + Integer storeMinOrderPrice, + + @NotBlank + LocalDateTime storeStarTime, + + @NotBlank + LocalDateTime storeEndTime + +) { +} From 9b7911c27e4090fd2d3f41205adf70ba8895b82f Mon Sep 17 00:00:00 2001 From: june-777 Date: Sun, 11 Aug 2024 22:15:25 +0900 Subject: [PATCH 25/77] =?UTF-8?q?[test]=20=EA=B0=80=EA=B2=8C=20=EB=93=B1?= =?UTF-8?q?=EB=A1=9D=20=EC=84=9C=EB=B9=84=EC=8A=A4=20=EB=A9=94=EC=84=9C?= =?UTF-8?q?=EB=93=9C=20=EB=8B=A8=EC=9C=84=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/StoreRegistrationServiceTest.java | 85 +++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 src/test/java/camp/woowak/lab/store/service/StoreRegistrationServiceTest.java diff --git a/src/test/java/camp/woowak/lab/store/service/StoreRegistrationServiceTest.java b/src/test/java/camp/woowak/lab/store/service/StoreRegistrationServiceTest.java new file mode 100644 index 00000000..9630dcef --- /dev/null +++ b/src/test/java/camp/woowak/lab/store/service/StoreRegistrationServiceTest.java @@ -0,0 +1,85 @@ +package camp.woowak.lab.store.service; + +import static org.mockito.BDDMockito.*; + +import java.time.LocalDateTime; +import java.util.Optional; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import camp.woowak.lab.infra.date.DateTimeProvider; +import camp.woowak.lab.store.domain.Store; +import camp.woowak.lab.store.domain.StoreCategory; +import camp.woowak.lab.store.exception.StoreException; +import camp.woowak.lab.store.repository.StoreCategoryRepository; +import camp.woowak.lab.store.repository.StoreRepository; +import camp.woowak.lab.vendor.domain.Vendor; + +@ExtendWith(MockitoExtension.class) +class StoreRegistrationServiceTest { + + @Mock + private StoreRepository storeRepository; + + @Mock + private StoreCategoryRepository storeCategoryRepository; + + @InjectMocks + private StoreRegistrationService storeRegistrationService; + + DateTimeProvider fixedStartTime = () -> LocalDateTime.of(2024, 8, 24, 1, 0, 0); + DateTimeProvider fixedEndTime = () -> LocalDateTime.of(2024, 8, 24, 5, 0, 0); + + LocalDateTime validStartTimeFixture = fixedStartTime.now(); + LocalDateTime validEndTimeFixture = fixedEndTime.now(); + + @Test + @DisplayName("[Success] 가게가 저장된다.") + void successfulRegistration() { + // given + Vendor vendor = new Vendor(); + String storeCategoryName = "한식"; + StoreRegistrationRequest request = createStoreRegistrationRequest(storeCategoryName); + StoreCategory mockStoreCategory = new StoreCategory(storeCategoryName); + + when(storeCategoryRepository.findByName(storeCategoryName)).thenReturn(Optional.of(mockStoreCategory)); + when(storeRepository.save(any(Store.class))) + .thenAnswer(invocation -> invocation.getArgument(0)); + + // when + storeRegistrationService.storeRegistration(vendor, request); + + // then + then(storeRepository).should().save(any(Store.class)); + } + + @Test + @DisplayName("[Exception] 유효하지 않은 가게 카테고리면 예외가 발생한다.") + void notExistStoreCategoryName() { + // given + Vendor vendor = new Vendor(); + String invalidCategoryName = "존재하지 않는 카테고리"; + StoreRegistrationRequest request = createStoreRegistrationRequest(invalidCategoryName); + + given(storeCategoryRepository.findByName(invalidCategoryName)) + .willReturn(Optional.empty()); + + // when & then + Assertions.assertThatThrownBy(() -> storeRegistrationService.storeRegistration(vendor, request)) + .isInstanceOf(StoreException.class); + + then(storeRepository).shouldHaveNoInteractions(); + } + + private StoreRegistrationRequest createStoreRegistrationRequest(String storeCategory) { + return new StoreRegistrationRequest("3K1K가게", "송파", "02-0000-0000", + storeCategory, 5000, validStartTimeFixture, validEndTimeFixture); + } + +} \ No newline at end of file From 790b465ec432bc61644787229991f2d7aacf6a16 Mon Sep 17 00:00:00 2001 From: june-777 Date: Sun, 11 Aug 2024 22:17:19 +0900 Subject: [PATCH 26/77] =?UTF-8?q?[fix]=20Order=20=EC=97=94=ED=8B=B0?= =?UTF-8?q?=ED=8B=B0=EC=9D=98=20=ED=85=8C=EC=9D=B4=EB=B8=94=20=EC=9D=B4?= =?UTF-8?q?=EB=A6=84=EC=9D=84=20Orders=20=EB=A1=9C=20=EB=AA=85=EC=8B=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit order 는 DBMS 예약어라서 Auto DDL 과정에서 예외가 발생함 --- .../camp/woowak/lab/order/domain/Order.java | 27 +++++++++++++------ 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/src/main/java/camp/woowak/lab/order/domain/Order.java b/src/main/java/camp/woowak/lab/order/domain/Order.java index 2f0a6bd7..bf7e8c42 100644 --- a/src/main/java/camp/woowak/lab/order/domain/Order.java +++ b/src/main/java/camp/woowak/lab/order/domain/Order.java @@ -2,15 +2,26 @@ import camp.woowak.lab.customer.domain.Customer; import camp.woowak.lab.store.domain.Store; -import jakarta.persistence.*; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; @Entity +@Table(name = "Orders") public class Order { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - @ManyToOne(fetch = FetchType.LAZY) - private Customer requester; - @ManyToOne(fetch = FetchType.LAZY) - private Store store; + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + private Customer requester; + + @ManyToOne(fetch = FetchType.LAZY) + private Store store; + } From 9c4a77d7017ffd52c2747f872431a1becea74802 Mon Sep 17 00:00:00 2001 From: june-777 Date: Sun, 11 Aug 2024 22:21:15 +0900 Subject: [PATCH 27/77] =?UTF-8?q?[feat]=20=EC=9D=B8=EB=A9=94=EB=AA=A8?= =?UTF-8?q?=EB=A6=AC=20H2=20DB=20=EB=B0=8F=20jpa=20yaml=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - datasource: 인메모리 H2 DB를 사용하도록 설정 - h2: h2 웹 콘솔 사용 가능하도록 설정 - jpa: ddl 자동 생성, sql 로깅 설정 - 설정 내용의 depth 가독성이 용이하여, properties 를 yaml 로 변경함 --- src/main/resources/application.properties | 1 - src/main/resources/application.yaml | 23 +++++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) delete mode 100644 src/main/resources/application.properties create mode 100644 src/main/resources/application.yaml diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties deleted file mode 100644 index cc1ad9a6..00000000 --- a/src/main/resources/application.properties +++ /dev/null @@ -1 +0,0 @@ -spring.application.name=lab diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml new file mode 100644 index 00000000..27cdd1fd --- /dev/null +++ b/src/main/resources/application.yaml @@ -0,0 +1,23 @@ +spring: + application: + name: lab + + datasource: + url: 'jdbc:h2:mem:lab' + driver-class-name: org.h2.Driver + username: sa + password: + + h2: + console: + enabled: true + path: /h2-console + + jpa: + hibernate: + ddl-auto: create + + properties: + hibernate: + format_sql: true + show_sql: true \ No newline at end of file From 680283fb8012c3c988b0bf4faa83729344c7639e Mon Sep 17 00:00:00 2001 From: june-777 Date: Sun, 11 Aug 2024 22:23:41 +0900 Subject: [PATCH 28/77] =?UTF-8?q?[refactor]=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20static=20=ED=82=A4=EC=9B=8C=EB=93=9C=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 --- .../camp/woowak/lab/store/service/StoreRegistrationService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/camp/woowak/lab/store/service/StoreRegistrationService.java b/src/main/java/camp/woowak/lab/store/service/StoreRegistrationService.java index 3b15d264..742cb97c 100644 --- a/src/main/java/camp/woowak/lab/store/service/StoreRegistrationService.java +++ b/src/main/java/camp/woowak/lab/store/service/StoreRegistrationService.java @@ -29,7 +29,7 @@ public void storeRegistration(final Vendor vendor, final StoreRegistrationReques storeRepository.save(store); } - private static Store createStore(Vendor vendor, StoreCategory storeCategory, StoreRegistrationRequest request) { + private Store createStore(Vendor vendor, StoreCategory storeCategory, StoreRegistrationRequest request) { return new Store(vendor, storeCategory, request.storeName(), request.storeAddress(), request.storePhoneNumber(), From 876e3fb2b2dc5eea2022aea2b7537208d6ec295b Mon Sep 17 00:00:00 2001 From: june-777 Date: Sun, 11 Aug 2024 22:38:37 +0900 Subject: [PATCH 29/77] =?UTF-8?q?[refactor]=20=EA=B0=80=EA=B2=8C=20?= =?UTF-8?q?=EB=93=B1=EB=A1=9D=20=EC=9A=94=EC=B2=AD=20DTO=20=ED=8C=A8?= =?UTF-8?q?=ED=82=A4=EC=A7=80=20=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../camp/woowak/lab/store/service/StoreRegistrationService.java | 1 + .../lab/store/service/{ => dto}/StoreRegistrationRequest.java | 2 +- .../woowak/lab/store/service/StoreRegistrationServiceTest.java | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) rename src/main/java/camp/woowak/lab/store/service/{ => dto}/StoreRegistrationRequest.java (90%) diff --git a/src/main/java/camp/woowak/lab/store/service/StoreRegistrationService.java b/src/main/java/camp/woowak/lab/store/service/StoreRegistrationService.java index 742cb97c..e68f2121 100644 --- a/src/main/java/camp/woowak/lab/store/service/StoreRegistrationService.java +++ b/src/main/java/camp/woowak/lab/store/service/StoreRegistrationService.java @@ -8,6 +8,7 @@ import camp.woowak.lab.store.exception.StoreException; import camp.woowak.lab.store.repository.StoreCategoryRepository; import camp.woowak.lab.store.repository.StoreRepository; +import camp.woowak.lab.store.service.dto.StoreRegistrationRequest; import camp.woowak.lab.vendor.domain.Vendor; import lombok.RequiredArgsConstructor; diff --git a/src/main/java/camp/woowak/lab/store/service/StoreRegistrationRequest.java b/src/main/java/camp/woowak/lab/store/service/dto/StoreRegistrationRequest.java similarity index 90% rename from src/main/java/camp/woowak/lab/store/service/StoreRegistrationRequest.java rename to src/main/java/camp/woowak/lab/store/service/dto/StoreRegistrationRequest.java index 6b2d1559..7968f09f 100644 --- a/src/main/java/camp/woowak/lab/store/service/StoreRegistrationRequest.java +++ b/src/main/java/camp/woowak/lab/store/service/dto/StoreRegistrationRequest.java @@ -1,4 +1,4 @@ -package camp.woowak.lab.store.service; +package camp.woowak.lab.store.service.dto; import java.time.LocalDateTime; diff --git a/src/test/java/camp/woowak/lab/store/service/StoreRegistrationServiceTest.java b/src/test/java/camp/woowak/lab/store/service/StoreRegistrationServiceTest.java index 9630dcef..63164b6d 100644 --- a/src/test/java/camp/woowak/lab/store/service/StoreRegistrationServiceTest.java +++ b/src/test/java/camp/woowak/lab/store/service/StoreRegistrationServiceTest.java @@ -19,6 +19,7 @@ import camp.woowak.lab.store.exception.StoreException; import camp.woowak.lab.store.repository.StoreCategoryRepository; import camp.woowak.lab.store.repository.StoreRepository; +import camp.woowak.lab.store.service.dto.StoreRegistrationRequest; import camp.woowak.lab.vendor.domain.Vendor; @ExtendWith(MockitoExtension.class) From 020ffbfbf72d0da6d409688b52bbd6dffc95f883 Mon Sep 17 00:00:00 2001 From: june-777 Date: Sun, 11 Aug 2024 23:46:58 +0900 Subject: [PATCH 30/77] =?UTF-8?q?[feat]=20=EA=B0=80=EA=B2=8C=EC=99=80=20?= =?UTF-8?q?=EA=B4=80=EB=A0=A8=EB=90=9C=20=EC=98=88=EC=99=B8=EB=A5=BC=20?= =?UTF-8?q?=EB=AA=85=EC=8B=9C=ED=95=98=EB=8A=94=20ErrorCode=20Enum=20?= =?UTF-8?q?=EC=A0=95=EC=9D=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 가게 관련한 예외의 범주를 ErrorCode Enum 으로 한정하도록 함 - 예외 메시지를 응집하여, 테스트 코드에서 예외 메시지 검증으로 구체적인 검증이 용이하도록 하기 위함 --- .../lab/store/exception/StoreException.java | 35 +++++++++++++++++-- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/src/main/java/camp/woowak/lab/store/exception/StoreException.java b/src/main/java/camp/woowak/lab/store/exception/StoreException.java index 33cd1642..628c6d6c 100644 --- a/src/main/java/camp/woowak/lab/store/exception/StoreException.java +++ b/src/main/java/camp/woowak/lab/store/exception/StoreException.java @@ -1,9 +1,38 @@ package camp.woowak.lab.store.exception; +import lombok.Getter; + +@Getter public class StoreException extends RuntimeException { - public StoreException(String message) { - super(message); + private final ErrorCode errorCode; + + public StoreException(final ErrorCode errorCode) { + super(errorCode.getMessage()); + this.errorCode = errorCode; } - + + @Getter + public enum ErrorCode { + + INVALID_NAME_RANGE("가게 이름은 2글자 ~ 10글자 이어야합니다."), + + INVALID_ADDRESS("가게 주소는 송파구만 가능합니다."), + + INVALID_MIN_ORDER_PRICE("최소 주문 금액은 5,000원 이상이어야 합니다."), + INVALID_UNIT_OF_MIN_ORDER_PRICE("최소 주문 금액은 1,000원 단위이어야 합니다."), + + INVALID_TIME_UNIT("가게 시작 시간은 분 단위까지 가능합니다"), + INVALID_TIME("가게 시작 시간은 종료 시간보다 이전이어야 합니다"), + + INVALID_STORE_CATEGORY("존재하지 않는 가게 카테고리입니다."); + + private final String message; + + ErrorCode(String message) { + this.message = message; + } + + } + } From 1f697f525be255a16663def30e455bc30110e7a0 Mon Sep 17 00:00:00 2001 From: june-777 Date: Sun, 11 Aug 2024 23:48:09 +0900 Subject: [PATCH 31/77] =?UTF-8?q?[refactor]=20StoreException=20=EC=9D=84?= =?UTF-8?q?=20=EC=83=9D=EC=84=B1=ED=95=A0=20=EB=95=8C,=20=EA=B0=80?= =?UTF-8?q?=EA=B2=8C=20=EA=B4=80=EB=A0=A8=20ErrorCode=20Enum=20=EC=9D=84?= =?UTF-8?q?=20=EC=83=9D=EC=84=B1=EC=9E=90=20=EB=A7=A4=EA=B0=9C=EB=B3=80?= =?UTF-8?q?=EC=88=98=EB=A1=9C=20=EC=82=AC=EC=9A=A9=ED=95=98=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lab/store/domain/StoreValidator.java | 18 ++++++++++-------- .../service/StoreRegistrationService.java | 4 +++- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/main/java/camp/woowak/lab/store/domain/StoreValidator.java b/src/main/java/camp/woowak/lab/store/domain/StoreValidator.java index ebcb133c..d17d0a3d 100644 --- a/src/main/java/camp/woowak/lab/store/domain/StoreValidator.java +++ b/src/main/java/camp/woowak/lab/store/domain/StoreValidator.java @@ -1,5 +1,7 @@ package camp.woowak.lab.store.domain; +import static camp.woowak.lab.store.exception.StoreException.ErrorCode.*; + import java.time.LocalDateTime; import camp.woowak.lab.store.exception.StoreException; @@ -27,7 +29,7 @@ private static void validateName(final String name) { if (MIN_NAME_LENGTH <= name.length() && name.length() <= MAX_NAME_LENGTH) { return; } - throw new StoreException("가게 이름은 2글자 ~ 10글자 이어야합니다."); + throw new StoreException(INVALID_NAME_RANGE); } // TODO: 가게 위치 비즈니스 요구사항 구체화하면, 주소 검증 로직 수정 예정 @@ -35,18 +37,18 @@ private static void validateAddress(final String address) { if (StoreAddress.DEFAULT_DISTRICT.equals(address)) { return; } - throw new StoreException("가게 주소는 송파구만 가능합니다."); + throw new StoreException(INVALID_ADDRESS); } private static void validateMinOrderPrice(final Integer minOrderPrice) { if (minOrderPrice < MIN_ORDER_PRICE) { - throw new StoreException("최소 주문 금액은 5,000원 이상이어야 합니다."); + throw new StoreException(INVALID_MIN_ORDER_PRICE); } } private static void validateUnitOrderPrice(final Integer minOrderPrice) { if (minOrderPrice % UNIT_OF_MIN_ORDER_PRICE != 0) { - throw new StoreException("최소 주문 금액은 1,000원 단위이어야 합니다."); + throw new StoreException(INVALID_UNIT_OF_MIN_ORDER_PRICE); } } @@ -54,19 +56,19 @@ private static void validateTime(final LocalDateTime startTime, final LocalDateTime endTime ) { if (isInvalidStoreTimeUnit(startTime)) { - throw new StoreException("가게 시작 시간은 분 단위까지 가능합니다"); + throw new StoreException(INVALID_TIME_UNIT); } if (isInvalidStoreTimeUnit(endTime)) { - throw new StoreException("가게 종료 시간은 분 단위까지 가능합니다"); + throw new StoreException(INVALID_TIME_UNIT); } if (endTime.isBefore(startTime)) { - throw new StoreException("가게 시작 시간은 종료 시간보다 이전이어야 합니다"); + throw new StoreException(INVALID_TIME); } if (startTime.isEqual(endTime)) { - throw new StoreException("가게 시작 시간과 종료 시간이 일치합니다"); + throw new StoreException(INVALID_TIME); } } diff --git a/src/main/java/camp/woowak/lab/store/service/StoreRegistrationService.java b/src/main/java/camp/woowak/lab/store/service/StoreRegistrationService.java index e68f2121..f4c385d8 100644 --- a/src/main/java/camp/woowak/lab/store/service/StoreRegistrationService.java +++ b/src/main/java/camp/woowak/lab/store/service/StoreRegistrationService.java @@ -1,5 +1,7 @@ package camp.woowak.lab.store.service; +import static camp.woowak.lab.store.exception.StoreException.ErrorCode.*; + import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -41,7 +43,7 @@ private Store createStore(Vendor vendor, StoreCategory storeCategory, StoreRegis private StoreCategory findStoreCategoryByName(final String name) { return storeCategoryRepository.findByName(name) - .orElseThrow(() -> new StoreException("존재하지 않는 가게 카테고리입니다.")); + .orElseThrow(() -> new StoreException(INVALID_STORE_CATEGORY)); } } From 3e5a748c5967a2d162bc8481be21ea433532f43c Mon Sep 17 00:00:00 2001 From: june-777 Date: Sun, 11 Aug 2024 23:48:53 +0900 Subject: [PATCH 32/77] =?UTF-8?q?[test]=20=EA=B0=80=EA=B2=8C=20=EB=93=B1?= =?UTF-8?q?=EB=A1=9D=20=EC=84=9C=EB=B9=84=EC=8A=A4=20=EC=98=88=EC=99=B8=20?= =?UTF-8?q?=EA=B2=80=EC=A6=9D=EC=9D=84=20=EC=98=88=EC=99=B8=20=EB=A9=94?= =?UTF-8?q?=EC=8B=9C=EC=A7=80=EB=A1=9C=20=EA=B5=AC=EC=B2=B4=EC=A0=81?= =?UTF-8?q?=EC=9D=B8=20=EA=B2=80=EC=A6=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lab/store/service/StoreRegistrationServiceTest.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/test/java/camp/woowak/lab/store/service/StoreRegistrationServiceTest.java b/src/test/java/camp/woowak/lab/store/service/StoreRegistrationServiceTest.java index 63164b6d..fd351bff 100644 --- a/src/test/java/camp/woowak/lab/store/service/StoreRegistrationServiceTest.java +++ b/src/test/java/camp/woowak/lab/store/service/StoreRegistrationServiceTest.java @@ -1,5 +1,6 @@ package camp.woowak.lab.store.service; +import static camp.woowak.lab.store.exception.StoreException.ErrorCode.*; import static org.mockito.BDDMockito.*; import java.time.LocalDateTime; @@ -73,7 +74,8 @@ void notExistStoreCategoryName() { // when & then Assertions.assertThatThrownBy(() -> storeRegistrationService.storeRegistration(vendor, request)) - .isInstanceOf(StoreException.class); + .isInstanceOf(StoreException.class) + .hasMessage(INVALID_STORE_CATEGORY.getMessage()); then(storeRepository).shouldHaveNoInteractions(); } From bd08a152e84e2810b4673ec7a44d9baa62ce8ee7 Mon Sep 17 00:00:00 2001 From: june-777 Date: Sun, 11 Aug 2024 23:49:02 +0900 Subject: [PATCH 33/77] =?UTF-8?q?[test]=20=EA=B0=80=EA=B2=8C=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=20=EC=98=88=EC=99=B8=20=EA=B2=80=EC=A6=9D=EC=9D=84=20?= =?UTF-8?q?=EC=98=88=EC=99=B8=20=EB=A9=94=EC=8B=9C=EC=A7=80=EB=A1=9C=20?= =?UTF-8?q?=EA=B5=AC=EC=B2=B4=EC=A0=81=EC=9D=B8=20=EA=B2=80=EC=A6=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../woowak/lab/store/domain/StoreTest.java | 34 +++++++++++++------ 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/src/test/java/camp/woowak/lab/store/domain/StoreTest.java b/src/test/java/camp/woowak/lab/store/domain/StoreTest.java index b6391d64..20b96e69 100644 --- a/src/test/java/camp/woowak/lab/store/domain/StoreTest.java +++ b/src/test/java/camp/woowak/lab/store/domain/StoreTest.java @@ -1,5 +1,6 @@ package camp.woowak.lab.store.domain; +import static camp.woowak.lab.store.exception.StoreException.ErrorCode.*; import static org.assertj.core.api.Assertions.*; import java.time.LocalDateTime; @@ -56,7 +57,8 @@ void lessThanMinOrderPrice() { assertThatThrownBy(() -> new Store(null, null, validNameFixture, validAddressFixture, null, lessThanMinOrderPrice, validStartTimeFixture, validEndTimeFixture)) - .isInstanceOf(StoreException.class); + .isInstanceOf(StoreException.class) + .hasMessage(INVALID_MIN_ORDER_PRICE.getMessage()); } @Test @@ -82,7 +84,8 @@ void inValidUnitOrderPrice() { assertThatThrownBy(() -> new Store(null, null, validNameFixture, validAddressFixture, null, inValidUnitOrderPrice, validStartTimeFixture, validEndTimeFixture)) - .isInstanceOf(StoreException.class); + .isInstanceOf(StoreException.class) + .hasMessage(INVALID_UNIT_OF_MIN_ORDER_PRICE.getMessage()); } } @@ -114,7 +117,8 @@ void endTimeSameWithStartTime() { assertThatThrownBy( () -> new Store(null, null, validNameFixture, validAddressFixture, null, validMinOrderPriceFixture, validStartTimeFixture, endTimeSameWithStartTime)) - .isInstanceOf(StoreException.class); + .isInstanceOf(StoreException.class) + .hasMessage(INVALID_TIME.getMessage()); } @Test @@ -127,7 +131,8 @@ void endTimeBeforeThanStartTime() { assertThatThrownBy( () -> new Store(null, null, validNameFixture, validAddressFixture, null, validMinOrderPriceFixture, validStartTimeFixture, endTimeBeforeThanStartTime)) - .isInstanceOf(StoreException.class); + .isInstanceOf(StoreException.class) + .hasMessage(INVALID_TIME.getMessage()); } @Test @@ -155,7 +160,8 @@ void startTimeWithSeconds() { assertThatThrownBy( () -> new Store(null, null, validNameFixture, validAddressFixture, null, validMinOrderPriceFixture, startTimeWithSeconds, validEndTimeFixture)) - .isInstanceOf(StoreException.class); + .isInstanceOf(StoreException.class) + .hasMessage(INVALID_TIME_UNIT.getMessage()); } @Test @@ -168,7 +174,8 @@ void startTimeWithNanoSeconds() { // when & then assertThatThrownBy(() -> new Store(null, null, validNameFixture, validAddressFixture, null, 5000, startTimeWithNanoSeconds, validEndTimeFixture)) - .isInstanceOf(StoreException.class); + .isInstanceOf(StoreException.class) + .hasMessage(INVALID_TIME_UNIT.getMessage()); } @Test @@ -181,7 +188,8 @@ void endTimeWithSeconds() { // when & then assertThatThrownBy(() -> new Store(null, null, validNameFixture, validAddressFixture, null, 5000, validStartTimeFixture, endTimeWithSeconds)) - .isInstanceOf(StoreException.class); + .isInstanceOf(StoreException.class) + .hasMessage(INVALID_TIME_UNIT.getMessage()); } @Test @@ -194,7 +202,8 @@ void endTimeWithNanoSeconds() { // when & then assertThatThrownBy(() -> new Store(null, null, validNameFixture, validAddressFixture, null, 5000, validStartTimeFixture, endTimeWithNanoSeconds)) - .isInstanceOf(StoreException.class); + .isInstanceOf(StoreException.class) + .hasMessage(INVALID_TIME_UNIT.getMessage()); } } @@ -226,7 +235,8 @@ void lessThanMinLengthName() { assertThatThrownBy(() -> new Store(null, null, lessThanMinLengthName, validAddressFixture, null, validMinOrderPriceFixture, validStartTimeFixture, validEndTimeFixture)) - .isInstanceOf(StoreException.class); + .isInstanceOf(StoreException.class) + .hasMessage(INVALID_NAME_RANGE.getMessage()); } @Test @@ -240,7 +250,8 @@ void greaterThanMaxLengthName() { () -> new Store(null, null, greaterThanMaxLengthName, validAddressFixture, null, validMinOrderPriceFixture, validStartTimeFixture, validEndTimeFixture)) - .isInstanceOf(StoreException.class); + .isInstanceOf(StoreException.class) + .hasMessage(INVALID_NAME_RANGE.getMessage()); } } @@ -270,7 +281,8 @@ void notSongPa() { assertThatThrownBy( () -> new Store(null, null, validNameFixture, validAddress, null, validMinOrderPriceFixture, validStartTimeFixture, validEndTimeFixture)) - .isInstanceOf(StoreException.class); + .isInstanceOf(StoreException.class) + .hasMessage(INVALID_ADDRESS.getMessage()); } } From 4160efddbc06ef8743c6d982806f17dd08c4b13d Mon Sep 17 00:00:00 2001 From: june-777 Date: Mon, 12 Aug 2024 01:04:01 +0900 Subject: [PATCH 34/77] =?UTF-8?q?[fix]=20Long,=20LocalDateTime=20=EB=8D=B0?= =?UTF-8?q?=EC=9D=B4=ED=84=B0=20=ED=83=80=EC=9E=85=EC=97=90=20=EB=8C=80?= =?UTF-8?q?=ED=95=9C=20Bean=20Validation=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @NotBlank 는 String 타입에 적용 가능 --- .../lab/store/service/dto/StoreRegistrationRequest.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/java/camp/woowak/lab/store/service/dto/StoreRegistrationRequest.java b/src/main/java/camp/woowak/lab/store/service/dto/StoreRegistrationRequest.java index 7968f09f..0b927adc 100644 --- a/src/main/java/camp/woowak/lab/store/service/dto/StoreRegistrationRequest.java +++ b/src/main/java/camp/woowak/lab/store/service/dto/StoreRegistrationRequest.java @@ -3,6 +3,7 @@ import java.time.LocalDateTime; import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; public record StoreRegistrationRequest( @@ -18,13 +19,13 @@ public record StoreRegistrationRequest( @NotBlank String storeCategoryName, - @NotBlank + @NotNull Integer storeMinOrderPrice, - @NotBlank + @NotNull LocalDateTime storeStarTime, - @NotBlank + @NotNull LocalDateTime storeEndTime ) { From fc53788fad5620ca2db728cba3863aa725781ac5 Mon Sep 17 00:00:00 2001 From: june-777 Date: Mon, 12 Aug 2024 01:04:47 +0900 Subject: [PATCH 35/77] =?UTF-8?q?[feat]=20Store=20=EA=B0=80=EA=B2=8C=20API?= =?UTF-8?q?=20=EC=BB=A8=ED=8A=B8=EB=A1=A4=EB=9F=AC=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lab/web/api/store/StoreApiController.java | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 src/main/java/camp/woowak/lab/web/api/store/StoreApiController.java diff --git a/src/main/java/camp/woowak/lab/web/api/store/StoreApiController.java b/src/main/java/camp/woowak/lab/web/api/store/StoreApiController.java new file mode 100644 index 00000000..3df7560a --- /dev/null +++ b/src/main/java/camp/woowak/lab/web/api/store/StoreApiController.java @@ -0,0 +1,32 @@ +package camp.woowak.lab.web.api.store; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + +import camp.woowak.lab.store.service.StoreRegistrationService; +import camp.woowak.lab.store.service.dto.StoreRegistrationRequest; +import camp.woowak.lab.vendor.domain.Vendor; +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; + +@RestController +@RequiredArgsConstructor +public class StoreApiController { + + private final StoreRegistrationService storeRegistrationService; + + // TODO: + // 1. 인증/인가에 대한 스펙이 정의되어야, Vendor Resolver 로직을 결정할 수 있음 + // 2. SSR, CSR 에 대해 통일해야, API 반환타입을 fix 할 수 있음 + // 3. API 공통 응답 명세에 대한 논의 진행 필요 + @PostMapping("/stores") + public ResponseEntity storeRegistration(final Vendor vendor, + final @Valid @RequestBody StoreRegistrationRequest request + ) { + storeRegistrationService.storeRegistration(vendor, request); + return ResponseEntity.ok().build(); + } + +} From 6ae068b54e29947c09c109d448840ded36e1d5ae Mon Sep 17 00:00:00 2001 From: june-777 Date: Mon, 12 Aug 2024 01:05:18 +0900 Subject: [PATCH 36/77] =?UTF-8?q?[feat]=20Store=20=EC=98=88=EC=99=B8=20?= =?UTF-8?q?=ED=95=B8=EB=93=A4=EB=9F=AC=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web/api/store/StoreExceptionHandler.java | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 src/main/java/camp/woowak/lab/web/api/store/StoreExceptionHandler.java diff --git a/src/main/java/camp/woowak/lab/web/api/store/StoreExceptionHandler.java b/src/main/java/camp/woowak/lab/web/api/store/StoreExceptionHandler.java new file mode 100644 index 00000000..ca2b86df --- /dev/null +++ b/src/main/java/camp/woowak/lab/web/api/store/StoreExceptionHandler.java @@ -0,0 +1,21 @@ +package camp.woowak.lab.web.api.store; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +import camp.woowak.lab.store.exception.StoreException; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@RestControllerAdvice +public class StoreExceptionHandler { + + @ExceptionHandler(StoreException.class) + public ResponseEntity handleException(StoreException exception) { + log.warn(exception.getMessage(), exception); + return new ResponseEntity<>("fail", HttpStatus.BAD_REQUEST); + } + +} From 882229067bd2f01674d9c0c87a2ae569136b7388 Mon Sep 17 00:00:00 2001 From: june-777 Date: Mon, 12 Aug 2024 01:05:23 +0900 Subject: [PATCH 37/77] =?UTF-8?q?[test]=20Store=20=EA=B0=80=EA=B2=8C=20API?= =?UTF-8?q?=20=EC=BB=A8=ED=8A=B8=EB=A1=A4=EB=9F=AC=20=EB=8B=A8=EC=9C=84=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web/api/store/StoreApiControllerTest.java | 105 ++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 src/test/java/camp/woowak/lab/web/api/store/StoreApiControllerTest.java diff --git a/src/test/java/camp/woowak/lab/web/api/store/StoreApiControllerTest.java b/src/test/java/camp/woowak/lab/web/api/store/StoreApiControllerTest.java new file mode 100644 index 00000000..faacf8d7 --- /dev/null +++ b/src/test/java/camp/woowak/lab/web/api/store/StoreApiControllerTest.java @@ -0,0 +1,105 @@ +package camp.woowak.lab.web.api.store; + +import static camp.woowak.lab.store.exception.StoreException.ErrorCode.*; +import static org.mockito.Mockito.*; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +import java.time.LocalDateTime; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; + +import camp.woowak.lab.infra.date.DateTimeProvider; +import camp.woowak.lab.store.exception.StoreException; +import camp.woowak.lab.store.service.StoreRegistrationService; +import camp.woowak.lab.store.service.dto.StoreRegistrationRequest; +import camp.woowak.lab.vendor.domain.Vendor; + +@WebMvcTest(StoreApiController.class) +class StoreApiControllerTest { + + @Autowired + private MockMvc mockMvc; + + @MockBean + private StoreRegistrationService storeRegistrationService; + + DateTimeProvider fixedStartTime = () -> LocalDateTime.of(2024, 8, 24, 1, 0, 0); + DateTimeProvider fixedEndTime = () -> LocalDateTime.of(2024, 8, 24, 5, 0, 0); + + LocalDateTime validStartTimeFixture = fixedStartTime.now(); + LocalDateTime validEndTimeFixture = fixedEndTime.now(); + + ObjectMapper objectMapper = new ObjectMapper(); + + @BeforeEach + void setUp() { + objectMapper = new ObjectMapper(); + objectMapper.registerModule(new JavaTimeModule()); + } + + @Test + @DisplayName("[Success] 200 OK") + void storeRegistrationSuccess() throws Exception { + // given + Vendor vendor = new Vendor(); + StoreRegistrationRequest request = new StoreRegistrationRequest( + "Store Name", + "Category Name", + "Store Address", + "123-456-7890", + 10000, + validStartTimeFixture, + validEndTimeFixture + ); + + // when & then + mockMvc.perform(post("/stores") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(request)) + .sessionAttr("vendor", vendor)) // TODO: 세션/JWT 인증 방식 토의 후, 정해진 방식에 맞게 수정 필요 (현재는 세션 방식으로 단위 테스트 진행) + .andExpect(status().isOk()) + .andExpect(content().string("")); + + verify(storeRegistrationService).storeRegistration(any(Vendor.class), any(StoreRegistrationRequest.class)); + } + + @Test + @DisplayName("[Exception] 400 Bad Request") + void storeRegistrationFailure() throws Exception { + // given + Vendor vendor = new Vendor(); // Vendor 객체 생성 방법에 따라 적절히 초기화 + StoreRegistrationRequest request = new StoreRegistrationRequest( + "Store Name", + "Invalid Category", + "Store Address", + "123-456-7890", + 10000, + validStartTimeFixture, + validEndTimeFixture + ); + + doThrow(new StoreException(INVALID_STORE_CATEGORY)) + .when(storeRegistrationService).storeRegistration(any(Vendor.class), any(StoreRegistrationRequest.class)); + + // when & then + mockMvc.perform(post("/stores") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(request)) + .sessionAttr("vendor", vendor)) // TODO: 세션/JWT 인증 방식 토의 후, 정해진 방식에 맞게 수정 필요 (현재는 세션 방식으로 단위 테스트 진행) + .andExpect(status().isBadRequest()) + .andExpect(content().string("fail")); + + verify(storeRegistrationService).storeRegistration(any(Vendor.class), any(StoreRegistrationRequest.class)); + } +} \ No newline at end of file From 03dd39009607b5e6f0317e037bad7a3f9854c9d3 Mon Sep 17 00:00:00 2001 From: june-777 Date: Tue, 13 Aug 2024 00:52:25 +0900 Subject: [PATCH 38/77] =?UTF-8?q?[feat]=20=EB=A9=94=EB=89=B4=EC=B9=B4?= =?UTF-8?q?=ED=85=8C=EA=B3=A0=EB=A6=AC=20=EC=97=94=ED=8B=B0=ED=8B=B0=20?= =?UTF-8?q?=EC=84=A4=EA=B3=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 설계 배경: 음식 상품을 등록할 때, 해당 가게에 등록한 음식 카테고리를 조회할 수 있어야함. 이와 연계하여, 매장에 대한 음식 카테고리를 등록할 수 있어야함. Enum 설계도 고려해봤지만, 동적으로 음식 카테고리를 추가하는데 제약이 있고, 메뉴 카테고리 조회에도 제약이 있다고 판단. 연관관계 설명: 메뉴-메뉴카테고리 (다대일): 하나의 메뉴는 하나의 메뉴 카테고리를 갖고, 하나의 메뉴 카테고리는 여러 메뉴에 속한다. 메뉴카테고리-매장 (다대일): 하나의 메뉴카테고리는 하나의 매장에 속하고, 하나의 매장은 여러 메뉴카테고리를 갖는다. --- .../camp/woowak/lab/menu/domain/Menu.java | 36 +++++++++++++++---- .../woowak/lab/menu/domain/MenuCategory.java | 35 ++++++++++++++++++ 2 files changed, 65 insertions(+), 6 deletions(-) create mode 100644 src/main/java/camp/woowak/lab/menu/domain/MenuCategory.java diff --git a/src/main/java/camp/woowak/lab/menu/domain/Menu.java b/src/main/java/camp/woowak/lab/menu/domain/Menu.java index efaaac92..525149c4 100644 --- a/src/main/java/camp/woowak/lab/menu/domain/Menu.java +++ b/src/main/java/camp/woowak/lab/menu/domain/Menu.java @@ -1,13 +1,37 @@ package camp.woowak.lab.menu.domain; import camp.woowak.lab.store.domain.Store; -import jakarta.persistence.*; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; @Entity public class Menu { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - @ManyToOne(fetch = FetchType.LAZY) - private Store store; + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "store_id", nullable = false) + private Store store; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "menu_category_id", nullable = false) + private MenuCategory menuCategory; + + @Column(nullable = false) + private String name; + + @Column(nullable = false) + private Integer price; + + @Column(nullable = true) + private String imageUrl; + } diff --git a/src/main/java/camp/woowak/lab/menu/domain/MenuCategory.java b/src/main/java/camp/woowak/lab/menu/domain/MenuCategory.java new file mode 100644 index 00000000..be8f8bb4 --- /dev/null +++ b/src/main/java/camp/woowak/lab/menu/domain/MenuCategory.java @@ -0,0 +1,35 @@ +package camp.woowak.lab.menu.domain; + +import camp.woowak.lab.store.domain.Store; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; + +@Entity +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class MenuCategory { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "store_id", nullable = false) + private Store store; + + @Column(nullable = false) + private String name; + + public MenuCategory(Store store, String name) { + this.store = store; + this.name = name; + } + +} From 5c9e3dbe5ce5e49a73206eddba0ca8c67ad571b0 Mon Sep 17 00:00:00 2001 From: june-777 Date: Tue, 13 Aug 2024 01:36:29 +0900 Subject: [PATCH 39/77] =?UTF-8?q?[feat]=20=EC=9D=8C=EC=8B=9D=20=EC=83=81?= =?UTF-8?q?=ED=92=88=EC=9D=B4=20=EC=9D=B4=EB=AF=B8=EC=A7=80=EB=A5=BC=20?= =?UTF-8?q?=EB=B0=98=EB=93=9C=EC=8B=9C=20=EA=B0=96=EB=8F=84=EB=A1=9D=20Nul?= =?UTF-8?q?lable=20=EC=A0=9C=EC=95=BD=EC=A1=B0=EA=B1=B4=20false=20?= =?UTF-8?q?=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/camp/woowak/lab/menu/domain/Menu.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/camp/woowak/lab/menu/domain/Menu.java b/src/main/java/camp/woowak/lab/menu/domain/Menu.java index 525149c4..55a7991e 100644 --- a/src/main/java/camp/woowak/lab/menu/domain/Menu.java +++ b/src/main/java/camp/woowak/lab/menu/domain/Menu.java @@ -31,7 +31,7 @@ public class Menu { @Column(nullable = false) private Integer price; - @Column(nullable = true) + @Column(nullable = false) private String imageUrl; } From eb2b17d878b96e368a0e648b3d6a23c145e5b7f2 Mon Sep 17 00:00:00 2001 From: june-777 Date: Tue, 13 Aug 2024 12:38:56 +0900 Subject: [PATCH 40/77] =?UTF-8?q?[feat]=20=EB=A9=94=EB=89=B4=20=EB=8F=84?= =?UTF-8?q?=EB=A9=94=EC=9D=B8=20Null=20=EA=B0=92=20=EA=B2=80=EC=A6=9D=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../woowak/lab/menu/domain/MenuValidator.java | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 src/main/java/camp/woowak/lab/menu/domain/MenuValidator.java diff --git a/src/main/java/camp/woowak/lab/menu/domain/MenuValidator.java b/src/main/java/camp/woowak/lab/menu/domain/MenuValidator.java new file mode 100644 index 00000000..20fe8a01 --- /dev/null +++ b/src/main/java/camp/woowak/lab/menu/domain/MenuValidator.java @@ -0,0 +1,23 @@ +package camp.woowak.lab.menu.domain; + +import camp.woowak.lab.menu.exception.InvalidMenuCreationException; +import camp.woowak.lab.store.domain.Store; + +public class MenuValidator { + + private static final int MAX_NAME_LENGTH = 10; + + public static void validate(final Store store, final MenuCategory menuCategory, final String name, + final Integer price, final String imageUrl) { + validateNotNull(store, menuCategory, name, price, imageUrl); + } + + private static void validateNotNull(final Object... targets) { + for (Object target : targets) { + if (target == null) { + throw new InvalidMenuCreationException(target + "은 Null 이 될 수 없습니다."); + } + } + } + +} From 66284d7389ef5b15c215e2844ee1e03f1e2a57be Mon Sep 17 00:00:00 2001 From: june-777 Date: Tue, 13 Aug 2024 12:39:40 +0900 Subject: [PATCH 41/77] =?UTF-8?q?[feat]=20=EB=A9=94=EB=89=B4=20=EB=8F=84?= =?UTF-8?q?=EB=A9=94=EC=9D=B8=20=EB=B9=88=20=EB=AC=B8=EC=9E=90=EC=97=B4,?= =?UTF-8?q?=20=EA=B3=B5=EB=B0=B1=20=EB=AC=B8=EC=9E=90=EC=97=B4=20=EA=B2=80?= =?UTF-8?q?=EC=A6=9D=20=EA=B8=B0=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/camp/woowak/lab/menu/domain/MenuValidator.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/main/java/camp/woowak/lab/menu/domain/MenuValidator.java b/src/main/java/camp/woowak/lab/menu/domain/MenuValidator.java index 20fe8a01..082b93b2 100644 --- a/src/main/java/camp/woowak/lab/menu/domain/MenuValidator.java +++ b/src/main/java/camp/woowak/lab/menu/domain/MenuValidator.java @@ -10,6 +10,7 @@ public class MenuValidator { public static void validate(final Store store, final MenuCategory menuCategory, final String name, final Integer price, final String imageUrl) { validateNotNull(store, menuCategory, name, price, imageUrl); + validateNotBlank(name, imageUrl); } private static void validateNotNull(final Object... targets) { @@ -20,4 +21,12 @@ private static void validateNotNull(final Object... targets) { } } + private static void validateNotBlank(final String... targets) { + for (String target : targets) { + if (target.isBlank()) { + throw new InvalidMenuCreationException(target + "은 빈 문자열이거나 공백 문자열이 포함될 수 없습니다."); + } + } + } + } From 2333c79d75429e0eecf0953e39ea1778638340ca Mon Sep 17 00:00:00 2001 From: june-777 Date: Tue, 13 Aug 2024 12:40:08 +0900 Subject: [PATCH 42/77] =?UTF-8?q?[feat]=20=EB=A9=94=EB=89=B4=20=EC=9D=B4?= =?UTF-8?q?=EB=A6=84=20=EA=B8=B8=EC=9D=B4=20=EA=B2=80=EC=A6=9D=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/camp/woowak/lab/menu/domain/MenuValidator.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/java/camp/woowak/lab/menu/domain/MenuValidator.java b/src/main/java/camp/woowak/lab/menu/domain/MenuValidator.java index 082b93b2..c8176b0f 100644 --- a/src/main/java/camp/woowak/lab/menu/domain/MenuValidator.java +++ b/src/main/java/camp/woowak/lab/menu/domain/MenuValidator.java @@ -11,6 +11,7 @@ public static void validate(final Store store, final MenuCategory menuCategory, final Integer price, final String imageUrl) { validateNotNull(store, menuCategory, name, price, imageUrl); validateNotBlank(name, imageUrl); + validateNameLength(name); } private static void validateNotNull(final Object... targets) { @@ -29,4 +30,10 @@ private static void validateNotBlank(final String... targets) { } } + private static void validateNameLength(final String name) { + if (name.length() > MAX_NAME_LENGTH) { + throw new InvalidMenuCreationException("메뉴 이름은 " + MAX_NAME_LENGTH + "글자까지 가능합니다."); + } + } + } From f1adbffc59eb62344420f1c49de9d6917e7613ea Mon Sep 17 00:00:00 2001 From: june-777 Date: Tue, 13 Aug 2024 12:41:43 +0900 Subject: [PATCH 43/77] =?UTF-8?q?[feat]=20=EB=A9=94=EB=89=B4=20=EA=B0=80?= =?UTF-8?q?=EA=B2=A9=20=EA=B2=80=EC=A6=9D=20=EA=B8=B0=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/camp/woowak/lab/menu/domain/MenuValidator.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/java/camp/woowak/lab/menu/domain/MenuValidator.java b/src/main/java/camp/woowak/lab/menu/domain/MenuValidator.java index c8176b0f..db0bc7e9 100644 --- a/src/main/java/camp/woowak/lab/menu/domain/MenuValidator.java +++ b/src/main/java/camp/woowak/lab/menu/domain/MenuValidator.java @@ -12,6 +12,7 @@ public static void validate(final Store store, final MenuCategory menuCategory, validateNotNull(store, menuCategory, name, price, imageUrl); validateNotBlank(name, imageUrl); validateNameLength(name); + validatePriceNegative(price); } private static void validateNotNull(final Object... targets) { @@ -36,4 +37,10 @@ private static void validateNameLength(final String name) { } } + private static void validatePriceNegative(final Integer price) { + if (price <= 0) { + throw new InvalidMenuCreationException("메뉴의 가격은 양수만 가능합니다"); + } + } + } From 122b5e7ac14ae94497b62cb4279887b5833d6edd Mon Sep 17 00:00:00 2001 From: june-777 Date: Tue, 13 Aug 2024 12:42:14 +0900 Subject: [PATCH 44/77] =?UTF-8?q?[feat]=20=EB=A9=94=EB=89=B4=20=EB=8F=84?= =?UTF-8?q?=EB=A9=94=EC=9D=B8=20=EC=83=9D=EC=84=B1=EC=9E=90=20=EB=B0=8F=20?= =?UTF-8?q?=EA=B2=80=EC=A6=9D=20=EA=B8=B0=EB=8A=A5=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/camp/woowak/lab/menu/domain/Menu.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/main/java/camp/woowak/lab/menu/domain/Menu.java b/src/main/java/camp/woowak/lab/menu/domain/Menu.java index 55a7991e..6b6f2dae 100644 --- a/src/main/java/camp/woowak/lab/menu/domain/Menu.java +++ b/src/main/java/camp/woowak/lab/menu/domain/Menu.java @@ -9,8 +9,11 @@ import jakarta.persistence.Id; import jakarta.persistence.JoinColumn; import jakarta.persistence.ManyToOne; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; @Entity +@NoArgsConstructor(access = AccessLevel.PROTECTED) public class Menu { @Id @@ -34,4 +37,13 @@ public class Menu { @Column(nullable = false) private String imageUrl; + public Menu(Store store, MenuCategory menuCategory, String name, Integer price, String imageUrl) { + MenuValidator.validate(store, menuCategory, name, price, imageUrl); + this.store = store; + this.menuCategory = menuCategory; + this.name = name; + this.price = price; + this.imageUrl = imageUrl; + } + } From 211b1abeb797a595f18296681ebc7165eaa8a865 Mon Sep 17 00:00:00 2001 From: june-777 Date: Tue, 13 Aug 2024 12:44:56 +0900 Subject: [PATCH 45/77] =?UTF-8?q?[test]=20Menu=20=EB=8F=84=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20=EA=B0=9D=EC=B2=B4=20=EC=83=9D=EC=84=B1=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20-=20=EA=B0=80=EA=B2=8C=20Null=20=EA=B0=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../camp/woowak/lab/menu/domain/MenuTest.java | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 src/test/java/camp/woowak/lab/menu/domain/MenuTest.java diff --git a/src/test/java/camp/woowak/lab/menu/domain/MenuTest.java b/src/test/java/camp/woowak/lab/menu/domain/MenuTest.java new file mode 100644 index 00000000..81fc93e7 --- /dev/null +++ b/src/test/java/camp/woowak/lab/menu/domain/MenuTest.java @@ -0,0 +1,57 @@ +package camp.woowak.lab.menu.domain; + +import static org.assertj.core.api.Assertions.*; + +import java.time.LocalDateTime; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import camp.woowak.lab.menu.exception.InvalidMenuCreationException; +import camp.woowak.lab.store.domain.Store; +import camp.woowak.lab.store.domain.StoreAddress; + +class MenuTest { + + Store storeFixture = createValidStore(); + MenuCategory menuCategoryFixture = createValidMenuCategory(); + + @Nested + @DisplayName("메뉴 생성은") + class MenuCreateTest { + + @Nested + @DisplayName("메뉴가 속한 가게가") + class MenuOfStore { + + @Test + @DisplayName("[Exception] Null 이면 InvalidMenuCreationException 이 발생한다") + void isNull() { + // given & when & then + assertThatCode(() -> new Menu(null, menuCategoryFixture, "1234", 1000, "image")) + .isInstanceOf(InvalidMenuCreationException.class); + } + + } + + } + + private Store createValidStore() { + LocalDateTime validStartDateFixture = LocalDateTime.of(2020, 1, 1, 1, 1); + LocalDateTime validEndDateFixture = LocalDateTime.of(2020, 1, 1, 2, 1); + String validNameFixture = "3K1K 가게"; + String validAddressFixture = StoreAddress.DEFAULT_DISTRICT; + String validPhoneNumberFixture = "02-1234-5678"; + Integer validMinOrderPriceFixture = 5000; + + return new Store(null, null, validNameFixture, validAddressFixture, validPhoneNumberFixture, + validMinOrderPriceFixture, + validStartDateFixture, validEndDateFixture); + } + + private MenuCategory createValidMenuCategory() { + return new MenuCategory(storeFixture, "1234567890"); + } + +} \ No newline at end of file From 3ecd00f4fbc77eee6ab8a252f086b7a2b1e0a835 Mon Sep 17 00:00:00 2001 From: june-777 Date: Tue, 13 Aug 2024 12:45:24 +0900 Subject: [PATCH 46/77] =?UTF-8?q?[test]=20Menu=20=EB=8F=84=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20=EA=B0=9D=EC=B2=B4=20=EC=83=9D=EC=84=B1=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20-=20=EB=A9=94=EB=89=B4=EC=B9=B4=ED=85=8C?= =?UTF-8?q?=EA=B3=A0=EB=A6=AC=20Null=20=EA=B0=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/camp/woowak/lab/menu/domain/MenuTest.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/test/java/camp/woowak/lab/menu/domain/MenuTest.java b/src/test/java/camp/woowak/lab/menu/domain/MenuTest.java index 81fc93e7..0501d6fe 100644 --- a/src/test/java/camp/woowak/lab/menu/domain/MenuTest.java +++ b/src/test/java/camp/woowak/lab/menu/domain/MenuTest.java @@ -35,6 +35,20 @@ void isNull() { } + @Nested + @DisplayName("메뉴카테고리가") + class MenuCategory { + + @Test + @DisplayName("[Exception] Null 이면 InvalidMenuCreationException 이 발생한다") + void isNull() { + // given & when & then + assertThatCode(() -> new Menu(storeFixture, null, "1234", 1000, "image")) + .isInstanceOf(InvalidMenuCreationException.class); + } + + } + } private Store createValidStore() { From c0025dd68f90f76cafa1affedc6777fdc64b0bba Mon Sep 17 00:00:00 2001 From: june-777 Date: Tue, 13 Aug 2024 12:46:08 +0900 Subject: [PATCH 47/77] =?UTF-8?q?[test]=20Menu=20=EB=8F=84=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20=EA=B0=9D=EC=B2=B4=20=EC=83=9D=EC=84=B1=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20-=20=EB=A9=94=EB=89=B4=20=EC=9D=B4?= =?UTF-8?q?=EB=A6=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../camp/woowak/lab/menu/domain/MenuTest.java | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/src/test/java/camp/woowak/lab/menu/domain/MenuTest.java b/src/test/java/camp/woowak/lab/menu/domain/MenuTest.java index 0501d6fe..29890780 100644 --- a/src/test/java/camp/woowak/lab/menu/domain/MenuTest.java +++ b/src/test/java/camp/woowak/lab/menu/domain/MenuTest.java @@ -49,6 +49,52 @@ void isNull() { } + @Nested + @DisplayName("메뉴 이름이") + class MenuName { + + @Test + @DisplayName("[Success] 10글자 이하만 가능하다") + void success() { + // given & when & then + assertThatCode(() -> new Menu(storeFixture, menuCategoryFixture, "1234567890", 1000, "image")) + .doesNotThrowAnyException(); + } + + @Test + @DisplayName("[Exception] Null 이면 InvalidMenuCreationException 이 발생한다") + void isNull() { + // given & when & then + assertThatCode(() -> new Menu(storeFixture, menuCategoryFixture, null, 1000, "image")) + .isInstanceOf(InvalidMenuCreationException.class); + } + + @Test + @DisplayName("[Exception] 빈 문자열이면 InvalidMenuCreationException 이 발생한다") + void isEmpty() { + // given & when & then + assertThatCode(() -> new Menu(storeFixture, menuCategoryFixture, "", 1000, "image")) + .isInstanceOf(InvalidMenuCreationException.class); + } + + @Test + @DisplayName("[Exception] 공백 문자열이면 InvalidMenuCreationException 이 발생한다") + void isBlank() { + // given & when & then + assertThatCode(() -> new Menu(storeFixture, menuCategoryFixture, " ", 1000, "image")) + .isInstanceOf(InvalidMenuCreationException.class); + } + + @Test + @DisplayName("[Exception] 10 글자를 초과하면 InvalidMenuCreationException 이 발생한다") + void greaterThanMaxNameLength() { + // given & when & then + assertThatCode(() -> new Menu(storeFixture, menuCategoryFixture, "12345678901", 1000, "image")) + .isInstanceOf(InvalidMenuCreationException.class); + } + + } + } private Store createValidStore() { From b6976d4c415a5cfa8e2ae81db188bc24595a363d Mon Sep 17 00:00:00 2001 From: june-777 Date: Tue, 13 Aug 2024 12:49:12 +0900 Subject: [PATCH 48/77] =?UTF-8?q?[test]=20Menu=20=EB=8F=84=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20=EA=B0=9D=EC=B2=B4=20=EC=83=9D=EC=84=B1=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20-=20=EB=A9=94=EB=89=B4=20=EA=B0=80?= =?UTF-8?q?=EA=B2=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../camp/woowak/lab/menu/domain/MenuTest.java | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/src/test/java/camp/woowak/lab/menu/domain/MenuTest.java b/src/test/java/camp/woowak/lab/menu/domain/MenuTest.java index 29890780..cc862d13 100644 --- a/src/test/java/camp/woowak/lab/menu/domain/MenuTest.java +++ b/src/test/java/camp/woowak/lab/menu/domain/MenuTest.java @@ -95,6 +95,44 @@ void greaterThanMaxNameLength() { } + @Nested + @DisplayName("메뉴 가격이") + class MenuPrice { + + @Test + @DisplayName("[Success] 양수만 가능하다") + void success() { + // given & when & then + assertThatCode(() -> new Menu(storeFixture, menuCategoryFixture, "1234567890", 1, "image")) + .doesNotThrowAnyException(); + } + + @Test + @DisplayName("[Exception] Null 이면 InvalidMenuCreationException 이 발생한다") + void isNull() { + // given & when & then + assertThatCode(() -> new Menu(storeFixture, menuCategoryFixture, "메뉴이름", null, "image")) + .isInstanceOf(InvalidMenuCreationException.class); + } + + @Test + @DisplayName("[Exception] 음수면 InvalidMenuCreationException 이 발생한다") + void isNegative() { + // given & when & then + assertThatCode(() -> new Menu(storeFixture, menuCategoryFixture, "메뉴이름", -1, "image")) + .isInstanceOf(InvalidMenuCreationException.class); + } + + @Test + @DisplayName("[Exception] 0이면 InvalidMenuCreationException 이 발생한다") + void isZero() { + // given & when & then + assertThatCode(() -> new Menu(storeFixture, menuCategoryFixture, "메뉴이름", 0, "image")) + .isInstanceOf(InvalidMenuCreationException.class); + } + + } + } private Store createValidStore() { From 976227b8d777775bf6199b0d6ae3727bafcc7c13 Mon Sep 17 00:00:00 2001 From: june-777 Date: Tue, 13 Aug 2024 12:49:24 +0900 Subject: [PATCH 49/77] =?UTF-8?q?[test]=20Menu=20=EB=8F=84=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20=EA=B0=9D=EC=B2=B4=20=EC=83=9D=EC=84=B1=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20-=20=EB=A9=94=EB=89=B4=20=EC=82=AC?= =?UTF-8?q?=EC=A7=84=20url?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../camp/woowak/lab/menu/domain/MenuTest.java | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/test/java/camp/woowak/lab/menu/domain/MenuTest.java b/src/test/java/camp/woowak/lab/menu/domain/MenuTest.java index cc862d13..c19cb5ca 100644 --- a/src/test/java/camp/woowak/lab/menu/domain/MenuTest.java +++ b/src/test/java/camp/woowak/lab/menu/domain/MenuTest.java @@ -133,6 +133,36 @@ void isZero() { } + @Nested + @DisplayName("메뉴 사진 url 이") + class MenuDescription { + + @Test + @DisplayName("[Exception] Null 이면 InvalidMenuCreationException 이 발생한다") + void isNull() { + // given & when & then + assertThatCode(() -> new Menu(storeFixture, menuCategoryFixture, null, 1000, "image")) + .isInstanceOf(InvalidMenuCreationException.class); + } + + @Test + @DisplayName("[Exception] 빈 문자열이면 InvalidMenuCreationException 이 발생한다") + void isEmpty() { + // given & when & then + assertThatCode(() -> new Menu(storeFixture, menuCategoryFixture, "", 1000, "image")) + .isInstanceOf(InvalidMenuCreationException.class); + } + + @Test + @DisplayName("[Exception] 공백 문자열이면 InvalidMenuCreationException 이 발생한다") + void isBlank() { + // given & when & then + assertThatCode(() -> new Menu(storeFixture, menuCategoryFixture, " ", 1000, "image")) + .isInstanceOf(InvalidMenuCreationException.class); + } + + } + } private Store createValidStore() { From 8862d1a273d70a09c29d8d8ba430a1d9ed5f091e Mon Sep 17 00:00:00 2001 From: june-777 Date: Tue, 13 Aug 2024 12:53:56 +0900 Subject: [PATCH 50/77] =?UTF-8?q?[feat]=20=EB=A9=94=EB=89=B4=EC=B9=B4?= =?UTF-8?q?=ED=85=8C=EA=B3=A0=EB=A6=AC=20=EB=8F=84=EB=A9=94=EC=9D=B8=20Nul?= =?UTF-8?q?l=20=EA=B0=92=20=EA=B2=80=EC=A6=9D=20=EA=B8=B0=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../menu/domain/MenuCategoryValidator.java | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 src/main/java/camp/woowak/lab/menu/domain/MenuCategoryValidator.java diff --git a/src/main/java/camp/woowak/lab/menu/domain/MenuCategoryValidator.java b/src/main/java/camp/woowak/lab/menu/domain/MenuCategoryValidator.java new file mode 100644 index 00000000..efc4681a --- /dev/null +++ b/src/main/java/camp/woowak/lab/menu/domain/MenuCategoryValidator.java @@ -0,0 +1,22 @@ +package camp.woowak.lab.menu.domain; + +import camp.woowak.lab.menu.exception.InvalidMenuCategoryCreationException; +import camp.woowak.lab.store.domain.Store; + +public class MenuCategoryValidator { + + private static final int MAX_NAME_LENGTH = 10; + + public static void validate(final Store store, final String name) { + validateNotNull(store, name); + } + + private static void validateNotNull(final Object... targets) { + for (Object target : targets) { + if (target == null) { + throw new InvalidMenuCategoryCreationException(target + "은 Null 이 될 수 없습니다."); + } + } + } + +} From 4b15f8ab94d2bc58bb598bbf16610a4b229171fb Mon Sep 17 00:00:00 2001 From: june-777 Date: Tue, 13 Aug 2024 12:54:50 +0900 Subject: [PATCH 51/77] =?UTF-8?q?[feat]=20=EB=A9=94=EB=89=B4=EC=B9=B4?= =?UTF-8?q?=ED=85=8C=EA=B3=A0=EB=A6=AC=20=EB=8F=84=EB=A9=94=EC=9D=B8=20?= =?UTF-8?q?=EB=B9=88=20=EB=AC=B8=EC=9E=90=EC=97=B4,=20=EA=B3=B5=EB=B0=B1?= =?UTF-8?q?=20=EB=AC=B8=EC=9E=90=EC=97=B4=20=EA=B2=80=EC=A6=9D=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../woowak/lab/menu/domain/MenuCategoryValidator.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/main/java/camp/woowak/lab/menu/domain/MenuCategoryValidator.java b/src/main/java/camp/woowak/lab/menu/domain/MenuCategoryValidator.java index efc4681a..004325ec 100644 --- a/src/main/java/camp/woowak/lab/menu/domain/MenuCategoryValidator.java +++ b/src/main/java/camp/woowak/lab/menu/domain/MenuCategoryValidator.java @@ -9,6 +9,7 @@ public class MenuCategoryValidator { public static void validate(final Store store, final String name) { validateNotNull(store, name); + validateNotBlank(name); } private static void validateNotNull(final Object... targets) { @@ -19,4 +20,12 @@ private static void validateNotNull(final Object... targets) { } } + private static void validateNotBlank(final String... targets) { + for (String target : targets) { + if (target.isBlank()) { + throw new InvalidMenuCategoryCreationException(target + "은 빈 문자열이거나 공백 문자열이 포함될 수 없습니다."); + } + } + } + } From 5ac5d9aed321dd4da9ab00baae0ac9aa4e8438f0 Mon Sep 17 00:00:00 2001 From: june-777 Date: Tue, 13 Aug 2024 12:55:18 +0900 Subject: [PATCH 52/77] =?UTF-8?q?[feat]=20=EB=A9=94=EB=89=B4=EC=B9=B4?= =?UTF-8?q?=ED=85=8C=EA=B3=A0=EB=A6=AC=20=EC=9D=B4=EB=A6=84=20=EA=B8=B8?= =?UTF-8?q?=EC=9D=B4=20=EA=B2=80=EC=A6=9D=20=EA=B8=B0=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../camp/woowak/lab/menu/domain/MenuCategoryValidator.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/java/camp/woowak/lab/menu/domain/MenuCategoryValidator.java b/src/main/java/camp/woowak/lab/menu/domain/MenuCategoryValidator.java index 004325ec..26f9c71b 100644 --- a/src/main/java/camp/woowak/lab/menu/domain/MenuCategoryValidator.java +++ b/src/main/java/camp/woowak/lab/menu/domain/MenuCategoryValidator.java @@ -10,6 +10,7 @@ public class MenuCategoryValidator { public static void validate(final Store store, final String name) { validateNotNull(store, name); validateNotBlank(name); + validateNameLength(name); } private static void validateNotNull(final Object... targets) { @@ -27,5 +28,11 @@ private static void validateNotBlank(final String... targets) { } } } + + private static void validateNameLength(final String name) { + if (name.length() > MAX_NAME_LENGTH) { + throw new InvalidMenuCategoryCreationException("메뉴 카테고리 이름은 " + MAX_NAME_LENGTH + "글자까지 가능합니다."); + } + } } From 5303c20b6c27e2fe8019f8d3b26b81bc9845ac42 Mon Sep 17 00:00:00 2001 From: june-777 Date: Tue, 13 Aug 2024 12:55:44 +0900 Subject: [PATCH 53/77] =?UTF-8?q?[feat]=20=EB=A9=94=EB=89=B4=EC=B9=B4?= =?UTF-8?q?=ED=85=8C=EA=B3=A0=EB=A6=AC=20=EC=83=9D=EC=84=B1=EC=9E=90?= =?UTF-8?q?=EC=97=90=20=EA=B2=80=EC=A6=9D=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/camp/woowak/lab/menu/domain/MenuCategory.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/camp/woowak/lab/menu/domain/MenuCategory.java b/src/main/java/camp/woowak/lab/menu/domain/MenuCategory.java index be8f8bb4..2e8d10b2 100644 --- a/src/main/java/camp/woowak/lab/menu/domain/MenuCategory.java +++ b/src/main/java/camp/woowak/lab/menu/domain/MenuCategory.java @@ -28,6 +28,7 @@ public class MenuCategory { private String name; public MenuCategory(Store store, String name) { + MenuCategoryValidator.validate(store, name); this.store = store; this.name = name; } From e24502df7543c795b6349980a38b72f7105d757a Mon Sep 17 00:00:00 2001 From: june-777 Date: Tue, 13 Aug 2024 12:56:29 +0900 Subject: [PATCH 54/77] =?UTF-8?q?[feat]=20=EB=A9=94=EB=89=B4=EC=B9=B4?= =?UTF-8?q?=ED=85=8C=EA=B3=A0=EB=A6=AC=20=EA=B0=9D=EC=B2=B4=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=20=EC=8B=A4=ED=8C=A8=20=EC=BB=A4=EC=8A=A4=ED=85=80=20?= =?UTF-8?q?=EC=98=88=EC=99=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../InvalidMenuCategoryCreationException.java | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 src/main/java/camp/woowak/lab/menu/exception/InvalidMenuCategoryCreationException.java diff --git a/src/main/java/camp/woowak/lab/menu/exception/InvalidMenuCategoryCreationException.java b/src/main/java/camp/woowak/lab/menu/exception/InvalidMenuCategoryCreationException.java new file mode 100644 index 00000000..5b3aeba8 --- /dev/null +++ b/src/main/java/camp/woowak/lab/menu/exception/InvalidMenuCategoryCreationException.java @@ -0,0 +1,10 @@ +package camp.woowak.lab.menu.exception; + +// TODO: extends CustomException +public class InvalidMenuCategoryCreationException extends RuntimeException { + + public InvalidMenuCategoryCreationException(String message) { + super(message); + } + +} From 0b17749fa490a6204b2cbad5569b9807d0eefe47 Mon Sep 17 00:00:00 2001 From: june-777 Date: Tue, 13 Aug 2024 12:56:35 +0900 Subject: [PATCH 55/77] =?UTF-8?q?[feat]=20=EB=A9=94=EB=89=B4=20=EA=B0=9D?= =?UTF-8?q?=EC=B2=B4=20=EC=83=9D=EC=84=B1=20=EC=8B=A4=ED=8C=A8=20=EC=BB=A4?= =?UTF-8?q?=EC=8A=A4=ED=85=80=20=EC=98=88=EC=99=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../menu/exception/InvalidMenuCreationException.java | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 src/main/java/camp/woowak/lab/menu/exception/InvalidMenuCreationException.java diff --git a/src/main/java/camp/woowak/lab/menu/exception/InvalidMenuCreationException.java b/src/main/java/camp/woowak/lab/menu/exception/InvalidMenuCreationException.java new file mode 100644 index 00000000..3e7ed471 --- /dev/null +++ b/src/main/java/camp/woowak/lab/menu/exception/InvalidMenuCreationException.java @@ -0,0 +1,10 @@ +package camp.woowak.lab.menu.exception; + +// TODO: extends CustomException +public class InvalidMenuCreationException extends RuntimeException { + + public InvalidMenuCreationException(String message) { + super(message); + } + +} From 7e8e9534759fe1baa451054a0e98374fd820806c Mon Sep 17 00:00:00 2001 From: june-777 Date: Tue, 13 Aug 2024 13:05:15 +0900 Subject: [PATCH 56/77] =?UTF-8?q?[test]=20MenuCategory=20=EB=8F=84?= =?UTF-8?q?=EB=A9=94=EC=9D=B8=20=EA=B0=9D=EC=B2=B4=20=EC=83=9D=EC=84=B1=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20-=20=EA=B0=80=EA=B2=8C=20Null=20?= =?UTF-8?q?=EA=B0=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lab/menu/domain/MenuCategoryTest.java | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 src/test/java/camp/woowak/lab/menu/domain/MenuCategoryTest.java diff --git a/src/test/java/camp/woowak/lab/menu/domain/MenuCategoryTest.java b/src/test/java/camp/woowak/lab/menu/domain/MenuCategoryTest.java new file mode 100644 index 00000000..e6fd850c --- /dev/null +++ b/src/test/java/camp/woowak/lab/menu/domain/MenuCategoryTest.java @@ -0,0 +1,52 @@ +package camp.woowak.lab.menu.domain; + +import static org.assertj.core.api.Assertions.*; + +import java.time.LocalDateTime; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import camp.woowak.lab.menu.exception.InvalidMenuCategoryCreationException; +import camp.woowak.lab.store.domain.Store; +import camp.woowak.lab.store.domain.StoreAddress; + +class MenuCategoryTest { + + @Nested + @DisplayName("메뉴 카테고리 생성은") + class MenuCategoryCreateTest { + + Store storeFixture = createValidStore(); + + @Nested + @DisplayName("메뉴 카테고리에 대한 가게가") + class StoreOfMenu { + + @Test + @DisplayName("[Exception] Null 이면 InvalidMenuCategoryCreationException 이 발생한다") + void isNull() { + // given & when & then + assertThatCode(() -> new MenuCategory(null, "가게")) + .isInstanceOf(InvalidMenuCategoryCreationException.class); + } + + } + + } + + private Store createValidStore() { + LocalDateTime validStartDateFixture = LocalDateTime.of(2020, 1, 1, 1, 1); + LocalDateTime validEndDateFixture = LocalDateTime.of(2020, 1, 1, 2, 1); + String validNameFixture = "3K1K 가게"; + String validAddressFixture = StoreAddress.DEFAULT_DISTRICT; + String validPhoneNumberFixture = "02-1234-5678"; + Integer validMinOrderPriceFixture = 5000; + + return new Store(null, null, validNameFixture, validAddressFixture, validPhoneNumberFixture, + validMinOrderPriceFixture, + validStartDateFixture, validEndDateFixture); + } + +} \ No newline at end of file From b4b31512fd54ea4290cc690921dcd97748f2b107 Mon Sep 17 00:00:00 2001 From: june-777 Date: Tue, 13 Aug 2024 13:05:59 +0900 Subject: [PATCH 57/77] =?UTF-8?q?[test]=20MenuCategory=20=EB=8F=84?= =?UTF-8?q?=EB=A9=94=EC=9D=B8=20=EA=B0=9D=EC=B2=B4=20=EC=83=9D=EC=84=B1=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20-=20=EC=9D=B4=EB=A6=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lab/menu/domain/MenuCategoryTest.java | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/src/test/java/camp/woowak/lab/menu/domain/MenuCategoryTest.java b/src/test/java/camp/woowak/lab/menu/domain/MenuCategoryTest.java index e6fd850c..61593e4b 100644 --- a/src/test/java/camp/woowak/lab/menu/domain/MenuCategoryTest.java +++ b/src/test/java/camp/woowak/lab/menu/domain/MenuCategoryTest.java @@ -34,6 +34,52 @@ void isNull() { } + @Nested + @DisplayName("이름이") + class MenuName { + + @Test + @DisplayName("[Success] 10글자 이하만 가능하다") + void success() { + // given & when & then + assertThatCode(() -> new MenuCategory(storeFixture, "1234567890")) + .doesNotThrowAnyException(); + } + + @Test + @DisplayName("[Exception] Null 이면 InvalidMenuCreationException 이 발생한다") + void isNull() { + // given & when & then + assertThatCode(() -> new MenuCategory(storeFixture, null)) + .isInstanceOf(InvalidMenuCategoryCreationException.class); + } + + @Test + @DisplayName("[Exception] 빈 문자열이면 InvalidMenuCreationException 이 발생한다") + void isEmpty() { + // given & when & then + assertThatCode(() -> new MenuCategory(storeFixture, "")) + .isInstanceOf(InvalidMenuCategoryCreationException.class); + } + + @Test + @DisplayName("[Exception] 공백 문자열이면 InvalidMenuCreationException 이 발생한다") + void isBlank() { + // given & when & then + assertThatCode(() -> new MenuCategory(storeFixture, " ")) + .isInstanceOf(InvalidMenuCategoryCreationException.class); + } + + @Test + @DisplayName("[Exception] 10 글자를 초과하면 InvalidMenuCreationException 이 발생한다") + void greaterThanMaxNameLength() { + // given & when & then + assertThatCode(() -> new MenuCategory(storeFixture, "12345678901")) + .isInstanceOf(InvalidMenuCategoryCreationException.class); + } + + } + } private Store createValidStore() { From f941ff9cbe32e131218fcbf0229bb48b479ff48a Mon Sep 17 00:00:00 2001 From: june-777 Date: Tue, 13 Aug 2024 14:25:15 +0900 Subject: [PATCH 58/77] =?UTF-8?q?[feat]=20=EC=A0=90=EC=A3=BC=20ID=20?= =?UTF-8?q?=EA=B8=B0=EB=B0=98=EC=9C=BC=EB=A1=9C=20=EB=A7=A4=EC=9E=A5?= =?UTF-8?q?=EC=9D=84=20=EC=A1=B0=ED=9A=8C=ED=95=98=EB=8A=94=20=EC=8B=9C?= =?UTF-8?q?=EA=B7=B8=EB=8B=88=EC=B3=90=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 점주가 가게 메뉴 등록 할 때, 점주에 대한 가게를 조회하는 로직이 필요함 --- .../camp/woowak/lab/store/repository/StoreRepository.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/camp/woowak/lab/store/repository/StoreRepository.java b/src/main/java/camp/woowak/lab/store/repository/StoreRepository.java index a4f98667..17ec6360 100644 --- a/src/main/java/camp/woowak/lab/store/repository/StoreRepository.java +++ b/src/main/java/camp/woowak/lab/store/repository/StoreRepository.java @@ -1,8 +1,13 @@ package camp.woowak.lab.store.repository; +import java.util.Optional; + import org.springframework.data.jpa.repository.JpaRepository; import camp.woowak.lab.store.domain.Store; public interface StoreRepository extends JpaRepository { + + Optional findByOwnerId(Long ownerId); + } From 41ffcc29dc9c5d0e70e27f36d7426f07cd0b52dc Mon Sep 17 00:00:00 2001 From: june-777 Date: Tue, 13 Aug 2024 14:25:25 +0900 Subject: [PATCH 59/77] =?UTF-8?q?[test]=20=EC=A0=90=EC=A3=BC=20ID=20?= =?UTF-8?q?=EA=B8=B0=EB=B0=98=EC=9C=BC=EB=A1=9C=20=EB=A7=A4=EC=9E=A5?= =?UTF-8?q?=EC=9D=84=20=EC=A1=B0=ED=9A=8C=ED=95=98=EB=8A=94=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../store/repository/StoreRepositoryTest.java | 102 +++++++++++++----- 1 file changed, 77 insertions(+), 25 deletions(-) diff --git a/src/test/java/camp/woowak/lab/store/repository/StoreRepositoryTest.java b/src/test/java/camp/woowak/lab/store/repository/StoreRepositoryTest.java index f04cc524..4ec6d636 100644 --- a/src/test/java/camp/woowak/lab/store/repository/StoreRepositoryTest.java +++ b/src/test/java/camp/woowak/lab/store/repository/StoreRepositoryTest.java @@ -1,9 +1,11 @@ package camp.woowak.lab.store.repository; +import static org.assertj.core.api.Assertions.*; + import java.time.LocalDateTime; -import org.assertj.core.api.Assertions; import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; @@ -39,38 +41,88 @@ class StoreRepositoryTest { String validPhoneNumberFixture = "02-0000-0000"; Integer validMinOrderPriceFixture = 5000; - @Test - @DisplayName("[Success] 가게 저장 성공") - void successfulSaveStore() { - // given - Vendor vendor = new Vendor(); - vendorRepository.saveAndFlush(vendor); + @Nested + @DisplayName("가게를 저장하는 기능은") + class SaveStore { + + @Test + @DisplayName("[Success] 가게 저장 성공") + void successfulSaveStore() { + // given + Vendor vendor = new Vendor(); + vendorRepository.saveAndFlush(vendor); + + StoreCategory storeCategory = new StoreCategory("한식"); + storeCategoryRepository.saveAndFlush(storeCategory); + + Store store = createStore(vendor, storeCategory); + + // when & then + assertThatCode(() -> storeRepository.save(store)) + .doesNotThrowAnyException(); + } + + @Test + @DisplayName("[Exception] 참조중인 엔티티가 저장되지 않았고, Not Null 제약조건이면 InvalidDataAccessApiUsageException - Not-null property 가 발생한다") + void test() { + // given + Vendor notSavedVendor = new Vendor(); + + StoreCategory storeCategory = new StoreCategory("한식"); + storeCategoryRepository.saveAndFlush(storeCategory); - StoreCategory storeCategory = new StoreCategory("한식"); - storeCategoryRepository.saveAndFlush(storeCategory); + // when + Store store = createStore(notSavedVendor, storeCategory); - Store store = createStore(vendor, storeCategory); + // then + assertThatThrownBy(() -> storeRepository.saveAndFlush(store)) + .isInstanceOf(InvalidDataAccessApiUsageException.class); + } - // when & then - Assertions.assertThatCode(() -> storeRepository.save(store)) - .doesNotThrowAnyException(); } - @Test - @DisplayName("[Exception] 참조중인 엔티티가 저장되지 않았고, Not Null 제약조건이면 InvalidDataAccessApiUsageException - Not-null property 가 발생한다") - void test() { - // given - Vendor notSavedVendor = new Vendor(); + @Nested + @DisplayName("점주 ID로 가게를 조회하는 기능은") + class FindByOwnerId { + + @Test + @DisplayName("[Success] 점주가 존재하는 경우 조회를 성공한다") + void success() { + // given + Vendor vendor = new Vendor(); + vendorRepository.saveAndFlush(vendor); + + StoreCategory storeCategory = new StoreCategory("한식"); + storeCategoryRepository.saveAndFlush(storeCategory); + + Store store = createStore(vendor, storeCategory); + storeRepository.saveAndFlush(store); + + // when & then + assertThat(storeRepository.findByOwnerId(vendor.getId())) + .isPresent() + .containsSame(store); + } + + @Test + @DisplayName("[Exception] 점주가 존재하지 않는 경우 빈 Optional 을 반환한다") + void notExistVendor() { + // given + Vendor vendor = new Vendor(); + vendorRepository.saveAndFlush(vendor); + Vendor notSavedVendor = new Vendor(); + + StoreCategory storeCategory = new StoreCategory("한식"); + storeCategoryRepository.saveAndFlush(storeCategory); - StoreCategory storeCategory = new StoreCategory("한식"); - storeCategoryRepository.saveAndFlush(storeCategory); + Store store = createStore(vendor, storeCategory); + storeRepository.saveAndFlush(store); - // when - Store store = createStore(notSavedVendor, storeCategory); + // when & then + assertThat(storeRepository.findByOwnerId(notSavedVendor.getId())) + .isEmpty(); + } - // then - Assertions.assertThatThrownBy(() -> storeRepository.saveAndFlush(store)) - .isInstanceOf(InvalidDataAccessApiUsageException.class); } private Store createStore(Vendor vendor, StoreCategory storeCategory) { From afee60d00b323f4a9b3bca44fae630947ba7fb13 Mon Sep 17 00:00:00 2001 From: june-777 Date: Tue, 13 Aug 2024 16:23:52 +0900 Subject: [PATCH 60/77] =?UTF-8?q?[feat]=20MenuCategoryRepository=20JPA=20?= =?UTF-8?q?=EC=9D=B8=ED=84=B0=ED=8E=98=EC=9D=B4=EC=8A=A4=20=EC=A0=95?= =?UTF-8?q?=EC=9D=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 가게ID와 메뉴카테고리 이름으로 메뉴카테고리를 조회하는 기능 --- .../lab/menu/repository/MenuCategoryRepository.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 src/main/java/camp/woowak/lab/menu/repository/MenuCategoryRepository.java diff --git a/src/main/java/camp/woowak/lab/menu/repository/MenuCategoryRepository.java b/src/main/java/camp/woowak/lab/menu/repository/MenuCategoryRepository.java new file mode 100644 index 00000000..708658c5 --- /dev/null +++ b/src/main/java/camp/woowak/lab/menu/repository/MenuCategoryRepository.java @@ -0,0 +1,13 @@ +package camp.woowak.lab.menu.repository; + +import java.util.Optional; + +import org.springframework.data.jpa.repository.JpaRepository; + +import camp.woowak.lab.menu.domain.MenuCategory; + +public interface MenuCategoryRepository extends JpaRepository { + + Optional findByStoreIdAndName(Long storeId, String name); + +} From c2a035e8c8168726b43603fc0d9f71e65b3b2b1b Mon Sep 17 00:00:00 2001 From: june-777 Date: Tue, 13 Aug 2024 16:24:25 +0900 Subject: [PATCH 61/77] =?UTF-8?q?[test]=20=EA=B0=80=EA=B2=8CID=EC=99=80=20?= =?UTF-8?q?=EB=A9=94=EB=89=B4=EC=B9=B4=ED=85=8C=EA=B3=A0=EB=A6=AC=20?= =?UTF-8?q?=EC=9D=B4=EB=A6=84=EC=9C=BC=EB=A1=9C=20=EB=A9=94=EB=89=B4?= =?UTF-8?q?=EC=B9=B4=ED=85=8C=EA=B3=A0=EB=A6=AC=EB=A5=BC=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=ED=95=98=EB=8A=94=20=EA=B8=B0=EB=8A=A5=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MenuCategoryRepositoryTest.java | 123 ++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 src/test/java/camp/woowak/lab/menu/repository/MenuCategoryRepositoryTest.java diff --git a/src/test/java/camp/woowak/lab/menu/repository/MenuCategoryRepositoryTest.java b/src/test/java/camp/woowak/lab/menu/repository/MenuCategoryRepositoryTest.java new file mode 100644 index 00000000..a20df6a5 --- /dev/null +++ b/src/test/java/camp/woowak/lab/menu/repository/MenuCategoryRepositoryTest.java @@ -0,0 +1,123 @@ +package camp.woowak.lab.menu.repository; + +import static org.assertj.core.api.Assertions.*; + +import java.time.LocalDateTime; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; + +import camp.woowak.lab.infra.date.DateTimeProvider; +import camp.woowak.lab.menu.domain.MenuCategory; +import camp.woowak.lab.store.domain.Store; +import camp.woowak.lab.store.domain.StoreAddress; +import camp.woowak.lab.store.domain.StoreCategory; +import camp.woowak.lab.store.repository.StoreCategoryRepository; +import camp.woowak.lab.store.repository.StoreRepository; +import camp.woowak.lab.vendor.domain.Vendor; +import camp.woowak.lab.vendor.repository.VendorRepository; + +@DataJpaTest +class MenuCategoryRepositoryTest { + + @Autowired + VendorRepository vendorRepository; + + @Autowired + StoreRepository storeRepository; + + @Autowired + MenuCategoryRepository menuCategoryRepository; + + @Autowired + StoreCategoryRepository storeCategoryRepository; + + @Nested + @DisplayName("가게와 메뉴카테고리 이름으로 메뉴카테고리를 조회하는 기능은") + class FindByStoreAndNameTest { + + @Test + @DisplayName("[Success] 가게와 메뉴카테고리 이름이 있으면 조회를 성공한다") + void success() { + // given + Vendor vendor = new Vendor(); + String categoryName = "돈가스"; + StoreCategory storeCategory = new StoreCategory(categoryName); + + vendorRepository.saveAndFlush(vendor); + storeCategoryRepository.saveAndFlush(storeCategory); + + Store store = createStore(vendor, storeCategory); + storeRepository.saveAndFlush(store); + MenuCategory menuCategory = new MenuCategory(store, categoryName); + menuCategoryRepository.save(menuCategory); + + // when & then + assertThat(menuCategoryRepository.findByStoreIdAndName(store.getId(), categoryName)) + .isPresent() + .containsSame(menuCategory); + } + + @Test + @DisplayName("[Exception] 가게가 없으면 빈 Optional 을 반환한다") + void notExistStore() { + // given + String categoryName = "돈가스"; + + // when & then + assertThat(menuCategoryRepository.findByStoreIdAndName(1234567L, categoryName)).isEmpty(); + } + + @Test + @DisplayName("[Exception] 메뉴카테고리 이름이 없으면 빈 Optional 을 반환한다") + void notExistMenuCategoryName() { + // given + String categoryName = "돈가스"; + String notExistCategoryName = "xxx"; + + Vendor vendor = new Vendor(); + vendorRepository.saveAndFlush(vendor); + + StoreCategory storeCategory = new StoreCategory(categoryName); + storeCategoryRepository.saveAndFlush(storeCategory); + + Store store = createStore(vendor, storeCategory); + storeRepository.saveAndFlush(store); + + MenuCategory menuCategory = new MenuCategory(store, categoryName); + menuCategoryRepository.save(menuCategory); + + // when & then + assertThat(menuCategoryRepository.findByStoreIdAndName(store.getId(), notExistCategoryName)) + .isEmpty(); + } + + } + + private Store createStore(Vendor vendor, StoreCategory storeCategory) { + DateTimeProvider fixedStartTime = () -> LocalDateTime.of(2024, 8, 24, 1, 0, 0); + DateTimeProvider fixedEndTime = () -> LocalDateTime.of(2024, 8, 24, 5, 0, 0); + + LocalDateTime validStartTimeFixture = fixedStartTime.now(); + LocalDateTime validEndTimeFixture = fixedEndTime.now(); + + String validNameFixture = "3K1K 가게"; + String validAddressFixture = StoreAddress.DEFAULT_DISTRICT; + String validPhoneNumberFixture = "02-0000-0000"; + Integer validMinOrderPriceFixture = 5000; + + return new Store(vendor, + storeCategory, + validNameFixture, + validAddressFixture, + validPhoneNumberFixture, + validMinOrderPriceFixture, + validStartTimeFixture, + validEndTimeFixture + ); + } + +} \ No newline at end of file From c430e050b34f427f90410f5b67f4ac264b2a5d2a Mon Sep 17 00:00:00 2001 From: june-777 Date: Tue, 13 Aug 2024 16:25:27 +0900 Subject: [PATCH 62/77] =?UTF-8?q?[feat]=20MenuRepository=20JPA=20=EC=9D=B8?= =?UTF-8?q?=ED=84=B0=ED=8E=98=EC=9D=B4=EC=8A=A4=20=EC=A0=95=EC=9D=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../camp/woowak/lab/menu/repository/MenuRepository.java | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 src/main/java/camp/woowak/lab/menu/repository/MenuRepository.java diff --git a/src/main/java/camp/woowak/lab/menu/repository/MenuRepository.java b/src/main/java/camp/woowak/lab/menu/repository/MenuRepository.java new file mode 100644 index 00000000..89305b0d --- /dev/null +++ b/src/main/java/camp/woowak/lab/menu/repository/MenuRepository.java @@ -0,0 +1,8 @@ +package camp.woowak.lab.menu.repository; + +import org.springframework.data.jpa.repository.JpaRepository; + +import camp.woowak.lab.menu.domain.Menu; + +public interface MenuRepository extends JpaRepository { +} From 6190a3e58a2ab621e1f9cae4fe85c36244c9cb40 Mon Sep 17 00:00:00 2001 From: june-777 Date: Tue, 13 Aug 2024 16:25:44 +0900 Subject: [PATCH 63/77] =?UTF-8?q?[feat]=20=EB=A9=94=EB=89=B4=20=EC=B9=B4?= =?UTF-8?q?=ED=85=8C=EA=B3=A0=EB=A6=AC=EB=A5=BC=20=EC=B0=BE=EC=9D=84=20?= =?UTF-8?q?=EC=88=98=20=EC=97=86=EB=8A=94=20=EC=BB=A4=EC=8A=A4=ED=85=80=20?= =?UTF-8?q?=EC=98=88=EC=99=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../menu/exception/NotFoundMenuCategoryException.java | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 src/main/java/camp/woowak/lab/menu/exception/NotFoundMenuCategoryException.java diff --git a/src/main/java/camp/woowak/lab/menu/exception/NotFoundMenuCategoryException.java b/src/main/java/camp/woowak/lab/menu/exception/NotFoundMenuCategoryException.java new file mode 100644 index 00000000..4e8ef121 --- /dev/null +++ b/src/main/java/camp/woowak/lab/menu/exception/NotFoundMenuCategoryException.java @@ -0,0 +1,10 @@ +package camp.woowak.lab.menu.exception; + +// TODO: extends CustomException +public class NotFoundMenuCategoryException extends RuntimeException { + + public NotFoundMenuCategoryException(String message) { + super(message); + } + +} From febd52972e58c766e5e6b1d4f15c261aca9181f4 Mon Sep 17 00:00:00 2001 From: june-777 Date: Tue, 13 Aug 2024 16:25:53 +0900 Subject: [PATCH 64/77] =?UTF-8?q?[feat]=20=EA=B0=80=EA=B2=8C=EB=A5=BC=20?= =?UTF-8?q?=EC=B0=BE=EC=9D=84=20=EC=88=98=20=EC=97=86=EB=8A=94=20=EC=BB=A4?= =?UTF-8?q?=EC=8A=A4=ED=85=80=20=EC=98=88=EC=99=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lab/store/exception/NotFoundStoreException.java | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 src/main/java/camp/woowak/lab/store/exception/NotFoundStoreException.java diff --git a/src/main/java/camp/woowak/lab/store/exception/NotFoundStoreException.java b/src/main/java/camp/woowak/lab/store/exception/NotFoundStoreException.java new file mode 100644 index 00000000..42848feb --- /dev/null +++ b/src/main/java/camp/woowak/lab/store/exception/NotFoundStoreException.java @@ -0,0 +1,10 @@ +package camp.woowak.lab.store.exception; + +// TODO: 404Exception 상속하도록 수정 +public class NotFoundStoreException extends RuntimeException { + + public NotFoundStoreException(String message) { + super(message); + } + +} From ab5a12d89b63b0e17bf4edb03f86cf37462d2251 Mon Sep 17 00:00:00 2001 From: june-777 Date: Tue, 13 Aug 2024 16:26:20 +0900 Subject: [PATCH 65/77] =?UTF-8?q?[feat]=20@Getter=20=EB=A1=AC=EB=B3=B5=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/camp/woowak/lab/store/domain/Store.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/camp/woowak/lab/store/domain/Store.java b/src/main/java/camp/woowak/lab/store/domain/Store.java index d67aeb3b..294004ce 100644 --- a/src/main/java/camp/woowak/lab/store/domain/Store.java +++ b/src/main/java/camp/woowak/lab/store/domain/Store.java @@ -14,10 +14,12 @@ import jakarta.persistence.ManyToOne; import jakarta.persistence.OneToOne; import lombok.AccessLevel; +import lombok.Getter; import lombok.NoArgsConstructor; @Entity @NoArgsConstructor(access = AccessLevel.PROTECTED) +@Getter public class Store { @Id From 29f410a112342e84ac1e3db21a1ab5b4da9b3284 Mon Sep 17 00:00:00 2001 From: june-777 Date: Tue, 13 Aug 2024 16:26:42 +0900 Subject: [PATCH 66/77] =?UTF-8?q?[feat]=20=EA=B0=80=EA=B2=8C=20=EB=A9=94?= =?UTF-8?q?=EB=89=B4=20=EB=93=B1=EB=A1=9D=20=EC=9A=94=EC=B2=AD=20DTO?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/StoreMenuRegistrationRequest.java | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 src/main/java/camp/woowak/lab/store/service/dto/StoreMenuRegistrationRequest.java diff --git a/src/main/java/camp/woowak/lab/store/service/dto/StoreMenuRegistrationRequest.java b/src/main/java/camp/woowak/lab/store/service/dto/StoreMenuRegistrationRequest.java new file mode 100644 index 00000000..e41fd873 --- /dev/null +++ b/src/main/java/camp/woowak/lab/store/service/dto/StoreMenuRegistrationRequest.java @@ -0,0 +1,27 @@ +package camp.woowak.lab.store.service.dto; + +import java.util.List; + +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; + +public record StoreMenuRegistrationRequest( + List menuItems +) { + + public record MenuLineItem( + @NotBlank + String name, + + @NotBlank + String imageUrl, + + @NotBlank + String categoryName, + + @NotNull + Integer price + ) { + } + +} From 6b0236fc17e3602d45cc448744192a8a3875ad2f Mon Sep 17 00:00:00 2001 From: june-777 Date: Tue, 13 Aug 2024 16:26:54 +0900 Subject: [PATCH 67/77] =?UTF-8?q?[feat]=20=EA=B0=80=EA=B2=8C=20=EB=A9=94?= =?UTF-8?q?=EB=89=B4=20=EB=93=B1=EB=A1=9D=20=EC=84=9C=EB=B9=84=EC=8A=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/StoreMenuRegistrationService.java | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 src/main/java/camp/woowak/lab/store/service/StoreMenuRegistrationService.java diff --git a/src/main/java/camp/woowak/lab/store/service/StoreMenuRegistrationService.java b/src/main/java/camp/woowak/lab/store/service/StoreMenuRegistrationService.java new file mode 100644 index 00000000..d0fad628 --- /dev/null +++ b/src/main/java/camp/woowak/lab/store/service/StoreMenuRegistrationService.java @@ -0,0 +1,66 @@ +package camp.woowak.lab.store.service; + +import java.util.List; + +import org.springframework.stereotype.Service; + +import camp.woowak.lab.menu.domain.Menu; +import camp.woowak.lab.menu.domain.MenuCategory; +import camp.woowak.lab.menu.exception.NotFoundMenuCategoryException; +import camp.woowak.lab.menu.repository.MenuCategoryRepository; +import camp.woowak.lab.menu.repository.MenuRepository; +import camp.woowak.lab.store.domain.Store; +import camp.woowak.lab.store.exception.NotFoundStoreException; +import camp.woowak.lab.store.repository.StoreRepository; +import camp.woowak.lab.store.service.dto.StoreMenuRegistrationRequest; +import camp.woowak.lab.vendor.domain.Vendor; +import lombok.RequiredArgsConstructor; + +/** + *

Description

+ * 가게 메뉴 등록을 담당 + * + *

User Story

+ * 점주는 음식 상품을 등록할 수 있다. + */ +@Service +@RequiredArgsConstructor +public class StoreMenuRegistrationService { + + private final StoreRepository storeRepository; + private final MenuRepository menuRepository; + private final MenuCategoryRepository menuCategoryRepository; + + public void storeMenuRegistration(final Vendor owner, final StoreMenuRegistrationRequest request) { + Store store = findStoreBy(owner.getId()); + + List menuLineItems = request.menuItems(); + List menus = createMenus(store, menuLineItems); + + menuRepository.saveAll(menus); + } + + private Store findStoreBy(final Long ownerId) { + return storeRepository.findByOwnerId(ownerId) + .orElseThrow(() -> new NotFoundStoreException("존재하지 않는 가게입니다.")); + } + + private List createMenus(final Store store, + final List menuLineItems + ) { + return menuLineItems.stream() + .map(menuLineItem -> createMenu(store, menuLineItem)) + .toList(); + } + + private Menu createMenu(final Store store, final StoreMenuRegistrationRequest.MenuLineItem menuLineItem) { + MenuCategory menuCategory = findMenuCategoryBy(store, menuLineItem.categoryName()); + return new Menu(store, menuCategory, menuLineItem.name(), menuLineItem.price(), menuLineItem.imageUrl()); + } + + private MenuCategory findMenuCategoryBy(final Store store, final String manuCategoryName) { + return menuCategoryRepository.findByStoreIdAndName(store.getId(), manuCategoryName) + .orElseThrow(() -> new NotFoundMenuCategoryException(store + ", " + manuCategoryName + " 의 메뉴카테고리가 없습니다.")); + } + +} From 817303409d4433d9d542aa9a4544f84c0e9a3029 Mon Sep 17 00:00:00 2001 From: june-777 Date: Tue, 13 Aug 2024 16:27:00 +0900 Subject: [PATCH 68/77] =?UTF-8?q?[test]=20=EA=B0=80=EA=B2=8C=20=EB=A9=94?= =?UTF-8?q?=EB=89=B4=20=EB=93=B1=EB=A1=9D=20=EC=84=9C=EB=B9=84=EC=8A=A4=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../StoreMenuRegistrationServiceTest.java | 102 ++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 src/test/java/camp/woowak/lab/store/service/StoreMenuRegistrationServiceTest.java diff --git a/src/test/java/camp/woowak/lab/store/service/StoreMenuRegistrationServiceTest.java b/src/test/java/camp/woowak/lab/store/service/StoreMenuRegistrationServiceTest.java new file mode 100644 index 00000000..7f9256ee --- /dev/null +++ b/src/test/java/camp/woowak/lab/store/service/StoreMenuRegistrationServiceTest.java @@ -0,0 +1,102 @@ +package camp.woowak.lab.store.service; + +import static org.assertj.core.api.Assertions.*; +import static org.mockito.Mockito.*; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.Optional; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import camp.woowak.lab.menu.domain.MenuCategory; +import camp.woowak.lab.menu.repository.MenuCategoryRepository; +import camp.woowak.lab.menu.repository.MenuRepository; +import camp.woowak.lab.store.domain.Store; +import camp.woowak.lab.store.domain.StoreAddress; +import camp.woowak.lab.store.exception.NotFoundStoreException; +import camp.woowak.lab.store.repository.StoreRepository; +import camp.woowak.lab.store.service.dto.StoreMenuRegistrationRequest; +import camp.woowak.lab.vendor.domain.Vendor; + +@ExtendWith(MockitoExtension.class) +class StoreMenuRegistrationServiceTest { + + @Mock + StoreRepository storeRepository; + + @Mock + MenuRepository menuRepository; + + @Mock + MenuCategoryRepository menuCategoryRepository; + + @InjectMocks + StoreMenuRegistrationService storeMenuRegistrationService; + + Store storeFixture = createValidStore(); + + MenuCategory menuCategoryFixture = createValidMenuCategory(); + + @Test + @DisplayName("[Success] 메뉴 등록 성공") + void storeMenuRegistrationSuccess() { + // given + Vendor owner = new Vendor(); + List menuItems = List.of( + new StoreMenuRegistrationRequest.MenuLineItem("메뉴1", "image1.jpg", "카테고리1", 10000) + ); + StoreMenuRegistrationRequest request = new StoreMenuRegistrationRequest(menuItems); + + when(storeRepository.findByOwnerId(owner.getId())).thenReturn(Optional.of(storeFixture)); + when(menuCategoryRepository.findByStoreIdAndName(storeFixture.getId(), "카테고리1")).thenReturn( + Optional.of(menuCategoryFixture)); + + // when + storeMenuRegistrationService.storeMenuRegistration(owner, request); + + // then + verify(storeRepository).findByOwnerId(owner.getId()); + verify(menuCategoryRepository).findByStoreIdAndName(storeFixture.getId(), "카테고리1"); + verify(menuRepository).saveAll(anyList()); + } + + @Test + @DisplayName("[Exception] 존재하지 않는 가게") + void storeMenuRegistrationStoreNotFound() { + // given + Vendor owner = new Vendor(); + List menuItems = List.of( + new StoreMenuRegistrationRequest.MenuLineItem("메뉴1", "image1.jpg", "카테고리1", 10000) + ); + StoreMenuRegistrationRequest request = new StoreMenuRegistrationRequest(menuItems); + + when(storeRepository.findByOwnerId(owner.getId())).thenReturn(Optional.empty()); + + // when & then + assertThatThrownBy(() -> storeMenuRegistrationService.storeMenuRegistration(owner, request)) + .isInstanceOf(NotFoundStoreException.class); + } + + private Store createValidStore() { + LocalDateTime validStartDateFixture = LocalDateTime.of(2020, 1, 1, 1, 1); + LocalDateTime validEndDateFixture = LocalDateTime.of(2020, 1, 1, 2, 1); + String validNameFixture = "3K1K 가게"; + String validAddressFixture = StoreAddress.DEFAULT_DISTRICT; + String validPhoneNumberFixture = "02-1234-5678"; + Integer validMinOrderPriceFixture = 5000; + + return new Store(null, null, validNameFixture, validAddressFixture, validPhoneNumberFixture, + validMinOrderPriceFixture, + validStartDateFixture, validEndDateFixture); + } + + private MenuCategory createValidMenuCategory() { + return new MenuCategory(storeFixture, "1234567890"); + } +} \ No newline at end of file From 7e606026b8d61f5ca04504cd33a4c208db86208c Mon Sep 17 00:00:00 2001 From: june-777 Date: Tue, 13 Aug 2024 16:27:27 +0900 Subject: [PATCH 69/77] =?UTF-8?q?[feat]=20Vendor=20@Getter=20=EB=A1=AC?= =?UTF-8?q?=EB=B3=B5=20=EC=B6=94=EA=B0=80=20=EB=B0=8F=20=EB=9D=BC=EC=9D=B8?= =?UTF-8?q?=20=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../camp/woowak/lab/vendor/domain/Vendor.java | 22 ++++++++++++++----- 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/src/main/java/camp/woowak/lab/vendor/domain/Vendor.java b/src/main/java/camp/woowak/lab/vendor/domain/Vendor.java index 41c924ce..4e022dd9 100644 --- a/src/main/java/camp/woowak/lab/vendor/domain/Vendor.java +++ b/src/main/java/camp/woowak/lab/vendor/domain/Vendor.java @@ -1,13 +1,23 @@ package camp.woowak.lab.vendor.domain; import camp.woowak.lab.payaccount.domain.PayAccount; -import jakarta.persistence.*; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.OneToOne; +import lombok.Getter; @Entity +@Getter public class Vendor { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - @OneToOne(fetch = FetchType.LAZY) - private PayAccount payAccount; + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @OneToOne(fetch = FetchType.LAZY) + private PayAccount payAccount; + } From d88f38cdeb7e20d9e189a5d39f250cd96b58bc85 Mon Sep 17 00:00:00 2001 From: june-777 Date: Wed, 14 Aug 2024 20:24:59 +0900 Subject: [PATCH 70/77] =?UTF-8?q?[test]=20merge=20=EA=B3=BC=EC=A0=95?= =?UTF-8?q?=EC=97=90=EC=84=9C=20=EA=B9=A8=EC=A7=80=EB=8A=94=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=EC=BD=94=EB=93=9C=20=EC=88=98=EC=A0=95=20?= =?UTF-8?q?=EB=B0=8F=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MenuCategoryRepositoryTest.java | 20 +++++++++++++++++-- .../StoreMenuRegistrationServiceTest.java | 15 ++++++++++++-- 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/src/test/java/camp/woowak/lab/menu/repository/MenuCategoryRepositoryTest.java b/src/test/java/camp/woowak/lab/menu/repository/MenuCategoryRepositoryTest.java index a20df6a5..37b7ceb5 100644 --- a/src/test/java/camp/woowak/lab/menu/repository/MenuCategoryRepositoryTest.java +++ b/src/test/java/camp/woowak/lab/menu/repository/MenuCategoryRepositoryTest.java @@ -12,6 +12,8 @@ import camp.woowak.lab.infra.date.DateTimeProvider; import camp.woowak.lab.menu.domain.MenuCategory; +import camp.woowak.lab.payaccount.domain.PayAccount; +import camp.woowak.lab.payaccount.repository.PayAccountRepository; import camp.woowak.lab.store.domain.Store; import camp.woowak.lab.store.domain.StoreAddress; import camp.woowak.lab.store.domain.StoreCategory; @@ -19,6 +21,8 @@ import camp.woowak.lab.store.repository.StoreRepository; import camp.woowak.lab.vendor.domain.Vendor; import camp.woowak.lab.vendor.repository.VendorRepository; +import camp.woowak.lab.web.authentication.NoOpPasswordEncoder; +import camp.woowak.lab.web.authentication.PasswordEncoder; @DataJpaTest class MenuCategoryRepositoryTest { @@ -35,6 +39,9 @@ class MenuCategoryRepositoryTest { @Autowired StoreCategoryRepository storeCategoryRepository; + @Autowired + PayAccountRepository payAccountRepository; + @Nested @DisplayName("가게와 메뉴카테고리 이름으로 메뉴카테고리를 조회하는 기능은") class FindByStoreAndNameTest { @@ -43,7 +50,9 @@ class FindByStoreAndNameTest { @DisplayName("[Success] 가게와 메뉴카테고리 이름이 있으면 조회를 성공한다") void success() { // given - Vendor vendor = new Vendor(); + PayAccount payAccount = payAccountRepository.save(new PayAccount()); + + Vendor vendor = createVendor(payAccount); String categoryName = "돈가스"; StoreCategory storeCategory = new StoreCategory(categoryName); @@ -77,8 +86,9 @@ void notExistMenuCategoryName() { // given String categoryName = "돈가스"; String notExistCategoryName = "xxx"; + PayAccount payAccount = payAccountRepository.save(new PayAccount()); - Vendor vendor = new Vendor(); + Vendor vendor = createVendor(payAccount); vendorRepository.saveAndFlush(vendor); StoreCategory storeCategory = new StoreCategory(categoryName); @@ -120,4 +130,10 @@ private Store createStore(Vendor vendor, StoreCategory storeCategory) { ); } + private Vendor createVendor(PayAccount payAccount) { + PasswordEncoder passwordEncoder = new NoOpPasswordEncoder(); + return new Vendor("vendorName", "vendorEmail@example.com", "vendorPassword", "010-0000-0000", payAccount, + passwordEncoder); + } + } \ No newline at end of file diff --git a/src/test/java/camp/woowak/lab/store/service/StoreMenuRegistrationServiceTest.java b/src/test/java/camp/woowak/lab/store/service/StoreMenuRegistrationServiceTest.java index 7f9256ee..afd1801e 100644 --- a/src/test/java/camp/woowak/lab/store/service/StoreMenuRegistrationServiceTest.java +++ b/src/test/java/camp/woowak/lab/store/service/StoreMenuRegistrationServiceTest.java @@ -17,12 +17,16 @@ import camp.woowak.lab.menu.domain.MenuCategory; import camp.woowak.lab.menu.repository.MenuCategoryRepository; import camp.woowak.lab.menu.repository.MenuRepository; +import camp.woowak.lab.payaccount.domain.PayAccount; +import camp.woowak.lab.payaccount.domain.TestPayAccount; import camp.woowak.lab.store.domain.Store; import camp.woowak.lab.store.domain.StoreAddress; import camp.woowak.lab.store.exception.NotFoundStoreException; import camp.woowak.lab.store.repository.StoreRepository; import camp.woowak.lab.store.service.dto.StoreMenuRegistrationRequest; import camp.woowak.lab.vendor.domain.Vendor; +import camp.woowak.lab.web.authentication.NoOpPasswordEncoder; +import camp.woowak.lab.web.authentication.PasswordEncoder; @ExtendWith(MockitoExtension.class) class StoreMenuRegistrationServiceTest { @@ -47,7 +51,7 @@ class StoreMenuRegistrationServiceTest { @DisplayName("[Success] 메뉴 등록 성공") void storeMenuRegistrationSuccess() { // given - Vendor owner = new Vendor(); + Vendor owner = createVendor(); List menuItems = List.of( new StoreMenuRegistrationRequest.MenuLineItem("메뉴1", "image1.jpg", "카테고리1", 10000) ); @@ -70,7 +74,7 @@ void storeMenuRegistrationSuccess() { @DisplayName("[Exception] 존재하지 않는 가게") void storeMenuRegistrationStoreNotFound() { // given - Vendor owner = new Vendor(); + Vendor owner = createVendor(); List menuItems = List.of( new StoreMenuRegistrationRequest.MenuLineItem("메뉴1", "image1.jpg", "카테고리1", 10000) ); @@ -99,4 +103,11 @@ private Store createValidStore() { private MenuCategory createValidMenuCategory() { return new MenuCategory(storeFixture, "1234567890"); } + + private Vendor createVendor() { + PayAccount payAccount = new TestPayAccount(1L); + PasswordEncoder passwordEncoder = new NoOpPasswordEncoder(); + return new Vendor("vendorName", "vendorEmail@example.com", "vendorPassword", "010-0000-0000", payAccount, + passwordEncoder); + } } \ No newline at end of file From f2de80c7b6aadfb8df308a2906b74c8217d56223 Mon Sep 17 00:00:00 2001 From: june-777 Date: Wed, 14 Aug 2024 20:31:21 +0900 Subject: [PATCH 71/77] =?UTF-8?q?[feat]=20=EA=B0=80=EA=B2=8C=20=EB=A9=94?= =?UTF-8?q?=EB=89=B4=20=EB=93=B1=EB=A1=9D=20=EC=9A=94=EC=B2=AD=20Bean=20Va?= =?UTF-8?q?lidation=20=EC=98=88=EC=99=B8=20=EB=A9=94=EC=8B=9C=EC=A7=80=20?= =?UTF-8?q?=EA=B5=AC=EC=B2=B4=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../store/service/dto/StoreMenuRegistrationRequest.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/camp/woowak/lab/store/service/dto/StoreMenuRegistrationRequest.java b/src/main/java/camp/woowak/lab/store/service/dto/StoreMenuRegistrationRequest.java index e41fd873..1d36f5c1 100644 --- a/src/main/java/camp/woowak/lab/store/service/dto/StoreMenuRegistrationRequest.java +++ b/src/main/java/camp/woowak/lab/store/service/dto/StoreMenuRegistrationRequest.java @@ -10,16 +10,16 @@ public record StoreMenuRegistrationRequest( ) { public record MenuLineItem( - @NotBlank + @NotBlank(message = "메뉴 이름은 필수값입니다.") String name, - @NotBlank + @NotBlank(message = "사진은 필수값입니다.") String imageUrl, - @NotBlank + @NotBlank(message = "메뉴 카테고리 이름은 필수값입니다.") String categoryName, - @NotNull + @NotNull(message = "메뉴 가격은 필수값입니다.") Integer price ) { } From 3c1ef855b3ddc7e21cc778f3c8dfced403e96398 Mon Sep 17 00:00:00 2001 From: june-777 Date: Thu, 15 Aug 2024 00:12:19 +0900 Subject: [PATCH 72/77] =?UTF-8?q?[feat]=20Store=20=EA=B0=9D=EC=B2=B4=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=20=EA=B2=80=EC=A6=9D=20=EC=A1=B0=EA=B1=B4=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20-=20Null=20=EC=B2=B4=ED=81=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../woowak/lab/store/domain/StoreValidator.java | 14 ++++++++++++-- .../woowak/lab/store/exception/StoreException.java | 1 + 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/main/java/camp/woowak/lab/store/domain/StoreValidator.java b/src/main/java/camp/woowak/lab/store/domain/StoreValidator.java index d17d0a3d..b8393cc4 100644 --- a/src/main/java/camp/woowak/lab/store/domain/StoreValidator.java +++ b/src/main/java/camp/woowak/lab/store/domain/StoreValidator.java @@ -5,6 +5,7 @@ import java.time.LocalDateTime; import camp.woowak.lab.store.exception.StoreException; +import camp.woowak.lab.vendor.domain.Vendor; public class StoreValidator { @@ -15,9 +16,11 @@ public class StoreValidator { private static final int MIN_NAME_LENGTH = 2; private static final int MAX_NAME_LENGTH = 10; - public static void validate(final String name, final String address, final Integer minOrderPrice, + public static void validate(final Vendor owner, StoreCategory storeCategory, final String name, + final String address, final Integer minOrderPrice, final LocalDateTime startTime, final LocalDateTime endTime ) { + validateNotNull(owner, storeCategory, name, address, minOrderPrice, startTime, endTime); validateName(name); validateAddress(address); validateMinOrderPrice(minOrderPrice); @@ -25,6 +28,14 @@ public static void validate(final String name, final String address, final Integ validateTime(startTime, endTime); } + private static void validateNotNull(Object... targets) { + for (Object target : targets) { + if (target == null) { + throw new StoreException(NULL_EXIST); + } + } + } + private static void validateName(final String name) { if (MIN_NAME_LENGTH <= name.length() && name.length() <= MAX_NAME_LENGTH) { return; @@ -32,7 +43,6 @@ private static void validateName(final String name) { throw new StoreException(INVALID_NAME_RANGE); } - // TODO: 가게 위치 비즈니스 요구사항 구체화하면, 주소 검증 로직 수정 예정 private static void validateAddress(final String address) { if (StoreAddress.DEFAULT_DISTRICT.equals(address)) { return; diff --git a/src/main/java/camp/woowak/lab/store/exception/StoreException.java b/src/main/java/camp/woowak/lab/store/exception/StoreException.java index 628c6d6c..a108d391 100644 --- a/src/main/java/camp/woowak/lab/store/exception/StoreException.java +++ b/src/main/java/camp/woowak/lab/store/exception/StoreException.java @@ -15,6 +15,7 @@ public StoreException(final ErrorCode errorCode) { @Getter public enum ErrorCode { + NULL_EXIST("NULL 값이 존재합니다."), INVALID_NAME_RANGE("가게 이름은 2글자 ~ 10글자 이어야합니다."), INVALID_ADDRESS("가게 주소는 송파구만 가능합니다."), From 70f5dfe85650e5bf30f94fa4a9f22e8fc1d3392c Mon Sep 17 00:00:00 2001 From: june-777 Date: Thu, 15 Aug 2024 00:13:06 +0900 Subject: [PATCH 73/77] =?UTF-8?q?[test]=20=EA=B8=B0=EC=A1=B4=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=BD=94=EB=93=9C=EC=9D=98=20Store=20?= =?UTF-8?q?=EA=B0=9D=EC=B2=B4=20=EC=83=9D=EC=84=B1=EC=9E=90=EC=97=90=20nul?= =?UTF-8?q?l=20=EC=A0=9C=EA=B1=B0=20=EB=B0=8F=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lab/menu/domain/MenuCategoryTest.java | 22 +++- .../camp/woowak/lab/menu/domain/MenuTest.java | 22 +++- .../woowak/lab/store/domain/StoreTest.java | 104 ++++++++++++------ .../StoreMenuRegistrationServiceTest.java | 29 +++-- 4 files changed, 133 insertions(+), 44 deletions(-) diff --git a/src/test/java/camp/woowak/lab/menu/domain/MenuCategoryTest.java b/src/test/java/camp/woowak/lab/menu/domain/MenuCategoryTest.java index 61593e4b..87febf38 100644 --- a/src/test/java/camp/woowak/lab/menu/domain/MenuCategoryTest.java +++ b/src/test/java/camp/woowak/lab/menu/domain/MenuCategoryTest.java @@ -9,8 +9,14 @@ import org.junit.jupiter.api.Test; import camp.woowak.lab.menu.exception.InvalidMenuCategoryCreationException; +import camp.woowak.lab.payaccount.domain.PayAccount; +import camp.woowak.lab.payaccount.domain.TestPayAccount; import camp.woowak.lab.store.domain.Store; import camp.woowak.lab.store.domain.StoreAddress; +import camp.woowak.lab.store.domain.StoreCategory; +import camp.woowak.lab.vendor.domain.Vendor; +import camp.woowak.lab.web.authentication.NoOpPasswordEncoder; +import camp.woowak.lab.web.authentication.PasswordEncoder; class MenuCategoryTest { @@ -90,9 +96,23 @@ private Store createValidStore() { String validPhoneNumberFixture = "02-1234-5678"; Integer validMinOrderPriceFixture = 5000; - return new Store(null, null, validNameFixture, validAddressFixture, validPhoneNumberFixture, + return new Store(createVendor(), createStoreCategory(), validNameFixture, validAddressFixture, + validPhoneNumberFixture, validMinOrderPriceFixture, validStartDateFixture, validEndDateFixture); } + private Vendor createVendor() { + PayAccount payAccount = new TestPayAccount(1L); + PasswordEncoder passwordEncoder = new NoOpPasswordEncoder(); + + return new Vendor("vendor", + "validEmail@validEmail.com", + "validPassword", "010-0000-0000", payAccount, passwordEncoder); + } + + private StoreCategory createStoreCategory() { + return new StoreCategory("양식"); + } + } \ No newline at end of file diff --git a/src/test/java/camp/woowak/lab/menu/domain/MenuTest.java b/src/test/java/camp/woowak/lab/menu/domain/MenuTest.java index c19cb5ca..79cb2c43 100644 --- a/src/test/java/camp/woowak/lab/menu/domain/MenuTest.java +++ b/src/test/java/camp/woowak/lab/menu/domain/MenuTest.java @@ -9,8 +9,14 @@ import org.junit.jupiter.api.Test; import camp.woowak.lab.menu.exception.InvalidMenuCreationException; +import camp.woowak.lab.payaccount.domain.PayAccount; +import camp.woowak.lab.payaccount.domain.TestPayAccount; import camp.woowak.lab.store.domain.Store; import camp.woowak.lab.store.domain.StoreAddress; +import camp.woowak.lab.store.domain.StoreCategory; +import camp.woowak.lab.vendor.domain.Vendor; +import camp.woowak.lab.web.authentication.NoOpPasswordEncoder; +import camp.woowak.lab.web.authentication.PasswordEncoder; class MenuTest { @@ -173,7 +179,8 @@ private Store createValidStore() { String validPhoneNumberFixture = "02-1234-5678"; Integer validMinOrderPriceFixture = 5000; - return new Store(null, null, validNameFixture, validAddressFixture, validPhoneNumberFixture, + return new Store(createVendor(), createStoreCategory(), validNameFixture, validAddressFixture, + validPhoneNumberFixture, validMinOrderPriceFixture, validStartDateFixture, validEndDateFixture); } @@ -182,4 +189,17 @@ private MenuCategory createValidMenuCategory() { return new MenuCategory(storeFixture, "1234567890"); } + private Vendor createVendor() { + PayAccount payAccount = new TestPayAccount(1L); + PasswordEncoder passwordEncoder = new NoOpPasswordEncoder(); + + return new Vendor("vendor", + "validEmail@validEmail.com", + "validPassword", "010-0000-0000", payAccount, passwordEncoder); + } + + private StoreCategory createStoreCategory() { + return new StoreCategory("양식"); + } + } \ No newline at end of file diff --git a/src/test/java/camp/woowak/lab/store/domain/StoreTest.java b/src/test/java/camp/woowak/lab/store/domain/StoreTest.java index 20b96e69..5d59985c 100644 --- a/src/test/java/camp/woowak/lab/store/domain/StoreTest.java +++ b/src/test/java/camp/woowak/lab/store/domain/StoreTest.java @@ -10,7 +10,12 @@ import org.junit.jupiter.api.Test; import camp.woowak.lab.infra.date.DateTimeProvider; +import camp.woowak.lab.payaccount.domain.PayAccount; +import camp.woowak.lab.payaccount.domain.TestPayAccount; import camp.woowak.lab.store.exception.StoreException; +import camp.woowak.lab.vendor.domain.Vendor; +import camp.woowak.lab.web.authentication.NoOpPasswordEncoder; +import camp.woowak.lab.web.authentication.PasswordEncoder; class StoreTest { @@ -41,9 +46,10 @@ void validMinOrderPrice() { int validMinOrderPrice = 5000; // when & then - assertThatCode(() -> new Store(null, null, validNameFixture, validAddressFixture, null, - validMinOrderPrice, - validStartTimeFixture, validEndTimeFixture)) + assertThatCode( + () -> new Store(createVendor(), createStoreCategory(), validNameFixture, validAddressFixture, null, + validMinOrderPrice, + validStartTimeFixture, validEndTimeFixture)) .doesNotThrowAnyException(); } @@ -54,9 +60,10 @@ void lessThanMinOrderPrice() { int lessThanMinOrderPrice = 4999; // when & then - assertThatThrownBy(() -> new Store(null, null, validNameFixture, validAddressFixture, null, - lessThanMinOrderPrice, - validStartTimeFixture, validEndTimeFixture)) + assertThatThrownBy( + () -> new Store(createVendor(), createStoreCategory(), validNameFixture, validAddressFixture, null, + lessThanMinOrderPrice, + validStartTimeFixture, validEndTimeFixture)) .isInstanceOf(StoreException.class) .hasMessage(INVALID_MIN_ORDER_PRICE.getMessage()); } @@ -68,9 +75,10 @@ void validUnitOrderPrice() { int validMinOrderPrice = 10000; // when & then - assertThatCode(() -> new Store(null, null, validNameFixture, validAddressFixture, null, - validMinOrderPrice, - validStartTimeFixture, validEndTimeFixture)) + assertThatCode( + () -> new Store(createVendor(), createStoreCategory(), validNameFixture, validAddressFixture, null, + validMinOrderPrice, + validStartTimeFixture, validEndTimeFixture)) .doesNotThrowAnyException(); } @@ -81,9 +89,10 @@ void inValidUnitOrderPrice() { int inValidUnitOrderPrice = 5001; // when & then - assertThatThrownBy(() -> new Store(null, null, validNameFixture, validAddressFixture, null, - inValidUnitOrderPrice, - validStartTimeFixture, validEndTimeFixture)) + assertThatThrownBy( + () -> new Store(createVendor(), createStoreCategory(), validNameFixture, validAddressFixture, null, + inValidUnitOrderPrice, + validStartTimeFixture, validEndTimeFixture)) .isInstanceOf(StoreException.class) .hasMessage(INVALID_UNIT_OF_MIN_ORDER_PRICE.getMessage()); } @@ -102,7 +111,8 @@ void storeStartTimeBeforeThanEndTime() { // when & then assertThatCode( - () -> new Store(null, null, validNameFixture, validAddressFixture, null, validMinOrderPriceFixture, + () -> new Store(createVendor(), createStoreCategory(), validNameFixture, validAddressFixture, null, + validMinOrderPriceFixture, validStartTime, validEndTime)) .doesNotThrowAnyException(); } @@ -115,7 +125,8 @@ void endTimeSameWithStartTime() { // when & then assertThatThrownBy( - () -> new Store(null, null, validNameFixture, validAddressFixture, null, validMinOrderPriceFixture, + () -> new Store(createVendor(), createStoreCategory(), validNameFixture, validAddressFixture, null, + validMinOrderPriceFixture, validStartTimeFixture, endTimeSameWithStartTime)) .isInstanceOf(StoreException.class) .hasMessage(INVALID_TIME.getMessage()); @@ -129,7 +140,8 @@ void endTimeBeforeThanStartTime() { // when & then assertThatThrownBy( - () -> new Store(null, null, validNameFixture, validAddressFixture, null, validMinOrderPriceFixture, + () -> new Store(createVendor(), createStoreCategory(), validNameFixture, validAddressFixture, null, + validMinOrderPriceFixture, validStartTimeFixture, endTimeBeforeThanStartTime)) .isInstanceOf(StoreException.class) .hasMessage(INVALID_TIME.getMessage()); @@ -144,7 +156,8 @@ void validStartTimeUnit() { // when & then assertThatCode( - () -> new Store(null, null, validNameFixture, validAddressFixture, null, validMinOrderPriceFixture, + () -> new Store(createVendor(), createStoreCategory(), validNameFixture, validAddressFixture, null, + validMinOrderPriceFixture, validStartTimeUnitMinute, validEndTimeUnitMinute)) .doesNotThrowAnyException(); } @@ -158,7 +171,8 @@ void startTimeWithSeconds() { // when & then assertThatThrownBy( - () -> new Store(null, null, validNameFixture, validAddressFixture, null, validMinOrderPriceFixture, + () -> new Store(createVendor(), createStoreCategory(), validNameFixture, validAddressFixture, null, + validMinOrderPriceFixture, startTimeWithSeconds, validEndTimeFixture)) .isInstanceOf(StoreException.class) .hasMessage(INVALID_TIME_UNIT.getMessage()); @@ -172,8 +186,10 @@ void startTimeWithNanoSeconds() { LocalDateTime startTimeWithNanoSeconds = inValidUnitDateTimeProvider.now(); // when & then - assertThatThrownBy(() -> new Store(null, null, validNameFixture, validAddressFixture, null, 5000, - startTimeWithNanoSeconds, validEndTimeFixture)) + assertThatThrownBy( + () -> new Store(createVendor(), createStoreCategory(), validNameFixture, validAddressFixture, null, + 5000, + startTimeWithNanoSeconds, validEndTimeFixture)) .isInstanceOf(StoreException.class) .hasMessage(INVALID_TIME_UNIT.getMessage()); } @@ -186,8 +202,10 @@ void endTimeWithSeconds() { LocalDateTime endTimeWithSeconds = inValidUnitDateTimeProvider.now(); // when & then - assertThatThrownBy(() -> new Store(null, null, validNameFixture, validAddressFixture, null, 5000, - validStartTimeFixture, endTimeWithSeconds)) + assertThatThrownBy( + () -> new Store(createVendor(), createStoreCategory(), validNameFixture, validAddressFixture, null, + 5000, + validStartTimeFixture, endTimeWithSeconds)) .isInstanceOf(StoreException.class) .hasMessage(INVALID_TIME_UNIT.getMessage()); } @@ -200,8 +218,10 @@ void endTimeWithNanoSeconds() { LocalDateTime endTimeWithNanoSeconds = inValidUnitDateTimeProvider.now(); // when & then - assertThatThrownBy(() -> new Store(null, null, validNameFixture, validAddressFixture, null, 5000, - validStartTimeFixture, endTimeWithNanoSeconds)) + assertThatThrownBy( + () -> new Store(createVendor(), createStoreCategory(), validNameFixture, validAddressFixture, null, + 5000, + validStartTimeFixture, endTimeWithNanoSeconds)) .isInstanceOf(StoreException.class) .hasMessage(INVALID_TIME_UNIT.getMessage()); } @@ -219,9 +239,11 @@ void validStoreName() { String lengthValidStoreName = validNameFixture; // when & then - assertThatCode(() -> new Store(null, null, lengthValidStoreName, validAddressFixture, null, - validMinOrderPriceFixture, - validStartTimeFixture, validEndTimeFixture)) + assertThatCode( + () -> new Store(createVendor(), createStoreCategory(), lengthValidStoreName, validAddressFixture, + null, + validMinOrderPriceFixture, + validStartTimeFixture, validEndTimeFixture)) .doesNotThrowAnyException(); } @@ -232,9 +254,11 @@ void lessThanMinLengthName() { String lessThanMinLengthName = "헤"; // when & then - assertThatThrownBy(() -> new Store(null, null, lessThanMinLengthName, validAddressFixture, null, - validMinOrderPriceFixture, - validStartTimeFixture, validEndTimeFixture)) + assertThatThrownBy( + () -> new Store(createVendor(), createStoreCategory(), lessThanMinLengthName, validAddressFixture, + null, + validMinOrderPriceFixture, + validStartTimeFixture, validEndTimeFixture)) .isInstanceOf(StoreException.class) .hasMessage(INVALID_NAME_RANGE.getMessage()); } @@ -247,7 +271,8 @@ void greaterThanMaxLengthName() { // when & then assertThatThrownBy( - () -> new Store(null, null, greaterThanMaxLengthName, validAddressFixture, null, + () -> new Store(createVendor(), createStoreCategory(), greaterThanMaxLengthName, + validAddressFixture, null, validMinOrderPriceFixture, validStartTimeFixture, validEndTimeFixture)) .isInstanceOf(StoreException.class) @@ -267,7 +292,8 @@ void onlySongPa() { String validAddress = "송파"; // when & then assertThatCode( - () -> new Store(null, null, validNameFixture, validAddress, null, validMinOrderPriceFixture, + () -> new Store(createVendor(), createStoreCategory(), validNameFixture, validAddress, null, + validMinOrderPriceFixture, validStartTimeFixture, validEndTimeFixture)) .doesNotThrowAnyException(); } @@ -279,7 +305,8 @@ void notSongPa() { String validAddress = "강남"; // when & then assertThatThrownBy( - () -> new Store(null, null, validNameFixture, validAddress, null, validMinOrderPriceFixture, + () -> new Store(createVendor(), createStoreCategory(), validNameFixture, validAddress, null, + validMinOrderPriceFixture, validStartTimeFixture, validEndTimeFixture)) .isInstanceOf(StoreException.class) .hasMessage(INVALID_ADDRESS.getMessage()); @@ -289,4 +316,17 @@ void notSongPa() { } + private Vendor createVendor() { + PayAccount payAccount = new TestPayAccount(1L); + PasswordEncoder passwordEncoder = new NoOpPasswordEncoder(); + + return new Vendor("vendor", + "validEmail@validEmail.com", + "validPassword", "010-0000-0000", payAccount, passwordEncoder); + } + + private StoreCategory createStoreCategory() { + return new StoreCategory("양식"); + } + } \ No newline at end of file diff --git a/src/test/java/camp/woowak/lab/store/service/StoreMenuRegistrationServiceTest.java b/src/test/java/camp/woowak/lab/store/service/StoreMenuRegistrationServiceTest.java index afd1801e..c46fd33b 100644 --- a/src/test/java/camp/woowak/lab/store/service/StoreMenuRegistrationServiceTest.java +++ b/src/test/java/camp/woowak/lab/store/service/StoreMenuRegistrationServiceTest.java @@ -21,6 +21,7 @@ import camp.woowak.lab.payaccount.domain.TestPayAccount; import camp.woowak.lab.store.domain.Store; import camp.woowak.lab.store.domain.StoreAddress; +import camp.woowak.lab.store.domain.StoreCategory; import camp.woowak.lab.store.exception.NotFoundStoreException; import camp.woowak.lab.store.repository.StoreRepository; import camp.woowak.lab.store.service.dto.StoreMenuRegistrationRequest; @@ -43,7 +44,8 @@ class StoreMenuRegistrationServiceTest { @InjectMocks StoreMenuRegistrationService storeMenuRegistrationService; - Store storeFixture = createValidStore(); + Vendor owner = createVendor(); + Store storeFixture = createValidStore(owner); MenuCategory menuCategoryFixture = createValidMenuCategory(); @@ -51,13 +53,14 @@ class StoreMenuRegistrationServiceTest { @DisplayName("[Success] 메뉴 등록 성공") void storeMenuRegistrationSuccess() { // given - Vendor owner = createVendor(); + Long storeId = 1L; + List menuItems = List.of( new StoreMenuRegistrationRequest.MenuLineItem("메뉴1", "image1.jpg", "카테고리1", 10000) ); - StoreMenuRegistrationRequest request = new StoreMenuRegistrationRequest(menuItems); + StoreMenuRegistrationRequest request = new StoreMenuRegistrationRequest(storeId, menuItems); - when(storeRepository.findByOwnerId(owner.getId())).thenReturn(Optional.of(storeFixture)); + when(storeRepository.findById(storeId)).thenReturn(Optional.of(storeFixture)); when(menuCategoryRepository.findByStoreIdAndName(storeFixture.getId(), "카테고리1")).thenReturn( Optional.of(menuCategoryFixture)); @@ -65,7 +68,7 @@ void storeMenuRegistrationSuccess() { storeMenuRegistrationService.storeMenuRegistration(owner, request); // then - verify(storeRepository).findByOwnerId(owner.getId()); + verify(storeRepository).findById(storeId); verify(menuCategoryRepository).findByStoreIdAndName(storeFixture.getId(), "카테고리1"); verify(menuRepository).saveAll(anyList()); } @@ -74,20 +77,21 @@ void storeMenuRegistrationSuccess() { @DisplayName("[Exception] 존재하지 않는 가게") void storeMenuRegistrationStoreNotFound() { // given - Vendor owner = createVendor(); + Long storeId = 1L; + List menuItems = List.of( new StoreMenuRegistrationRequest.MenuLineItem("메뉴1", "image1.jpg", "카테고리1", 10000) ); - StoreMenuRegistrationRequest request = new StoreMenuRegistrationRequest(menuItems); + StoreMenuRegistrationRequest request = new StoreMenuRegistrationRequest(storeId, menuItems); - when(storeRepository.findByOwnerId(owner.getId())).thenReturn(Optional.empty()); + when(storeRepository.findById(storeId)).thenReturn(Optional.empty()); // when & then assertThatThrownBy(() -> storeMenuRegistrationService.storeMenuRegistration(owner, request)) .isInstanceOf(NotFoundStoreException.class); } - private Store createValidStore() { + private Store createValidStore(Vendor owner) { LocalDateTime validStartDateFixture = LocalDateTime.of(2020, 1, 1, 1, 1); LocalDateTime validEndDateFixture = LocalDateTime.of(2020, 1, 1, 2, 1); String validNameFixture = "3K1K 가게"; @@ -95,7 +99,8 @@ private Store createValidStore() { String validPhoneNumberFixture = "02-1234-5678"; Integer validMinOrderPriceFixture = 5000; - return new Store(null, null, validNameFixture, validAddressFixture, validPhoneNumberFixture, + return new Store(owner, createStoreCategory(), validNameFixture, validAddressFixture, + validPhoneNumberFixture, validMinOrderPriceFixture, validStartDateFixture, validEndDateFixture); } @@ -110,4 +115,8 @@ private Vendor createVendor() { return new Vendor("vendorName", "vendorEmail@example.com", "vendorPassword", "010-0000-0000", payAccount, passwordEncoder); } + + private StoreCategory createStoreCategory() { + return new StoreCategory("양식"); + } } \ No newline at end of file From 6af2250e1042b0e9f662448ab95ee62e78a3f98a Mon Sep 17 00:00:00 2001 From: june-777 Date: Thu, 15 Aug 2024 00:13:33 +0900 Subject: [PATCH 74/77] =?UTF-8?q?[feat]=20=EA=B0=80=EA=B2=8C=20=EB=A9=94?= =?UTF-8?q?=EB=89=B4=20=EB=93=B1=EB=A1=9D=20=EC=9A=94=EC=B2=AD=20DTO?= =?UTF-8?q?=EC=97=90=20=EA=B0=80=EA=B2=8C=20ID=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lab/store/service/dto/StoreMenuRegistrationRequest.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/camp/woowak/lab/store/service/dto/StoreMenuRegistrationRequest.java b/src/main/java/camp/woowak/lab/store/service/dto/StoreMenuRegistrationRequest.java index 1d36f5c1..5a588aaa 100644 --- a/src/main/java/camp/woowak/lab/store/service/dto/StoreMenuRegistrationRequest.java +++ b/src/main/java/camp/woowak/lab/store/service/dto/StoreMenuRegistrationRequest.java @@ -6,6 +6,10 @@ import jakarta.validation.constraints.NotNull; public record StoreMenuRegistrationRequest( + @NotBlank(message = "가게 ID는 필수값입니다.") + Long storeId, + + @NotNull(message = "등록할 메뉴는 필수값입니다.") List menuItems ) { From a8fc0a8b23f66f5b16032e6c991a33193049b381 Mon Sep 17 00:00:00 2001 From: june-777 Date: Thu, 15 Aug 2024 00:15:03 +0900 Subject: [PATCH 75/77] =?UTF-8?q?[fix]=20=EA=B0=80=EA=B2=8C=20ID=EB=A1=9C?= =?UTF-8?q?=20=EA=B0=80=EA=B2=8C=EB=A5=BC=20=EC=A1=B0=ED=9A=8C=ED=95=98?= =?UTF-8?q?=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 점주 - 가게 일대다 관계로, 점주 ID로 조회하면 가게 목록을 조회하게 됨 --- .../camp/woowak/lab/store/repository/StoreRepository.java | 5 ----- .../lab/store/service/StoreMenuRegistrationService.java | 4 ++-- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/src/main/java/camp/woowak/lab/store/repository/StoreRepository.java b/src/main/java/camp/woowak/lab/store/repository/StoreRepository.java index 17ec6360..a4f98667 100644 --- a/src/main/java/camp/woowak/lab/store/repository/StoreRepository.java +++ b/src/main/java/camp/woowak/lab/store/repository/StoreRepository.java @@ -1,13 +1,8 @@ package camp.woowak.lab.store.repository; -import java.util.Optional; - import org.springframework.data.jpa.repository.JpaRepository; import camp.woowak.lab.store.domain.Store; public interface StoreRepository extends JpaRepository { - - Optional findByOwnerId(Long ownerId); - } diff --git a/src/main/java/camp/woowak/lab/store/service/StoreMenuRegistrationService.java b/src/main/java/camp/woowak/lab/store/service/StoreMenuRegistrationService.java index d0fad628..8f2836ed 100644 --- a/src/main/java/camp/woowak/lab/store/service/StoreMenuRegistrationService.java +++ b/src/main/java/camp/woowak/lab/store/service/StoreMenuRegistrationService.java @@ -40,8 +40,8 @@ public void storeMenuRegistration(final Vendor owner, final StoreMenuRegistratio menuRepository.saveAll(menus); } - private Store findStoreBy(final Long ownerId) { - return storeRepository.findByOwnerId(ownerId) + private Store findStoreBy(final Long storeId) { + return storeRepository.findById(storeId) .orElseThrow(() -> new NotFoundStoreException("존재하지 않는 가게입니다.")); } From c7eb0363118ed9b80e95c2e8397bca6ce774b8a2 Mon Sep 17 00:00:00 2001 From: june-777 Date: Thu, 15 Aug 2024 00:15:26 +0900 Subject: [PATCH 76/77] =?UTF-8?q?[feat]=20=EA=B0=80=EA=B2=8C=EC=9D=98=20?= =?UTF-8?q?=EC=A0=90=EC=A3=BC=EC=99=80=20=EB=8F=99=EC=9D=BC=ED=95=9C?= =?UTF-8?q?=EC=A7=80=20=EA=B2=80=EC=A6=9D=ED=95=98=EB=8A=94=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/camp/woowak/lab/store/domain/Store.java | 11 ++++++++--- .../store/service/StoreMenuRegistrationService.java | 5 +++-- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/main/java/camp/woowak/lab/store/domain/Store.java b/src/main/java/camp/woowak/lab/store/domain/Store.java index 294004ce..16fc444a 100644 --- a/src/main/java/camp/woowak/lab/store/domain/Store.java +++ b/src/main/java/camp/woowak/lab/store/domain/Store.java @@ -2,6 +2,7 @@ import java.time.LocalDateTime; +import camp.woowak.lab.store.exception.NotEqualsOwnerException; import camp.woowak.lab.vendor.domain.Vendor; import jakarta.persistence.Column; import jakarta.persistence.Embedded; @@ -37,8 +38,6 @@ public class Store { @Column(nullable = false) private String name; - // TODO: 위치 정보에 대한 요구사항 논의 후 수정 예정. - // i.g) 송파구로 특정, 도시 정보로 특정 등 요구사항이 정의되어야 엔티티 설계를 진행할 수 있음 @Embedded private StoreAddress storeAddress; @@ -54,7 +53,7 @@ public class Store { public Store(Vendor owner, StoreCategory storeCategory, String name, String address, String phoneNumber, Integer minOrderPrice, LocalDateTime startTime, LocalDateTime endTime ) { - StoreValidator.validate(name, address, minOrderPrice, startTime, endTime); + StoreValidator.validate(owner, storeCategory, name, address, minOrderPrice, startTime, endTime); this.owner = owner; this.storeCategory = storeCategory; this.name = name; @@ -64,4 +63,10 @@ public Store(Vendor owner, StoreCategory storeCategory, String name, String addr this.storeTime = new StoreTime(startTime, endTime); } + public void validateOwner(Vendor owner) { + if (!this.owner.equals(owner)) { + throw new NotEqualsOwnerException("가게의 점주가 일치하지 않습니다." + this.owner + ", " + owner); + } + } + } diff --git a/src/main/java/camp/woowak/lab/store/service/StoreMenuRegistrationService.java b/src/main/java/camp/woowak/lab/store/service/StoreMenuRegistrationService.java index 8f2836ed..6b8af6b4 100644 --- a/src/main/java/camp/woowak/lab/store/service/StoreMenuRegistrationService.java +++ b/src/main/java/camp/woowak/lab/store/service/StoreMenuRegistrationService.java @@ -32,8 +32,9 @@ public class StoreMenuRegistrationService { private final MenuCategoryRepository menuCategoryRepository; public void storeMenuRegistration(final Vendor owner, final StoreMenuRegistrationRequest request) { - Store store = findStoreBy(owner.getId()); - + Store store = findStoreBy(request.storeId()); + store.validateOwner(owner); + List menuLineItems = request.menuItems(); List menus = createMenus(store, menuLineItems); From d3ec39c3d63f9bd101227ad542d44b900830c407 Mon Sep 17 00:00:00 2001 From: june-777 Date: Thu, 15 Aug 2024 00:15:39 +0900 Subject: [PATCH 77/77] =?UTF-8?q?[feat]=20=EA=B0=80=EA=B2=8C=EC=9D=98=20?= =?UTF-8?q?=EC=A0=90=EC=A3=BC=EC=99=80=20=EB=8F=99=EC=9D=BC=ED=95=98?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EC=9D=84=20=EB=95=8C=20=EB=B0=9C=EC=83=9D?= =?UTF-8?q?=ED=95=98=EB=8A=94=20=EC=BB=A4=EC=8A=A4=ED=85=80=20=EC=98=88?= =?UTF-8?q?=EC=99=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lab/store/exception/NotEqualsOwnerException.java | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 src/main/java/camp/woowak/lab/store/exception/NotEqualsOwnerException.java diff --git a/src/main/java/camp/woowak/lab/store/exception/NotEqualsOwnerException.java b/src/main/java/camp/woowak/lab/store/exception/NotEqualsOwnerException.java new file mode 100644 index 00000000..f122216c --- /dev/null +++ b/src/main/java/camp/woowak/lab/store/exception/NotEqualsOwnerException.java @@ -0,0 +1,9 @@ +package camp.woowak.lab.store.exception; + +public class NotEqualsOwnerException extends RuntimeException { + + public NotEqualsOwnerException(String message) { + super(message); + } + +}