From 06070e27d39d23f09bcfdbe42d8ffca1014cb4ad Mon Sep 17 00:00:00 2001 From: HyuckJuneHong Date: Wed, 8 Nov 2023 16:23:50 +0900 Subject: [PATCH 01/10] =?UTF-8?q?feat:=20=EC=BF=A0=ED=8F=B0=20=EC=97=94?= =?UTF-8?q?=ED=8B=B0=ED=8B=B0=20=EC=84=A4=EA=B3=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/moabam/api/domain/entity/Coupon.java | 89 +++++++++++++++++++ .../api/domain/entity/CouponWallet.java | 44 +++++++++ .../api/domain/entity/enums/CouponType.java | 8 ++ .../global/error/model/ErrorMessage.java | 5 +- 4 files changed, 145 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/moabam/api/domain/entity/Coupon.java create mode 100644 src/main/java/com/moabam/api/domain/entity/CouponWallet.java create mode 100644 src/main/java/com/moabam/api/domain/entity/enums/CouponType.java diff --git a/src/main/java/com/moabam/api/domain/entity/Coupon.java b/src/main/java/com/moabam/api/domain/entity/Coupon.java new file mode 100644 index 00000000..3dcfa9b1 --- /dev/null +++ b/src/main/java/com/moabam/api/domain/entity/Coupon.java @@ -0,0 +1,89 @@ +package com.moabam.api.domain.entity; + +import static com.moabam.global.error.model.ErrorMessage.*; +import static java.util.Objects.*; + +import java.time.LocalDateTime; + +import org.hibernate.annotations.ColumnDefault; + +import com.moabam.api.domain.entity.enums.CouponType; +import com.moabam.global.common.entity.BaseTimeEntity; +import com.moabam.global.error.exception.BadRequestException; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.Table; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Entity +@Getter +@Table(name = "coupon") +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class Coupon extends BaseTimeEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "id") + private Long id; + + @Column(name = "name", nullable = false, unique = true) + private String name; + + @ColumnDefault("0") + @Column(name = "point", nullable = false) + private int point; + + @Column(name = "description") + private String description; + + @Enumerated(value = EnumType.STRING) + @Column(name = "type", nullable = false) + private CouponType type; + + @ColumnDefault("0") + @Column(name = "stock", nullable = false) + private int stock; + + @Column(name = "start_at", nullable = false) + private LocalDateTime startAt; + + @Column(name = "end_at", nullable = false) + private LocalDateTime endAt; + + @Builder + private Coupon(String name, int point, String description, CouponType type, int stock, LocalDateTime startAt, + LocalDateTime endAt) { + this.name = requireNonNull(name); + this.point = validatePoint(point); + this.description = description; + this.type = requireNonNull(type); + this.stock = validateStock(stock); + this.startAt = requireNonNull(startAt); + this.endAt = requireNonNull(endAt); + } + + private int validatePoint(int point) { + if (point < 0) { + throw new BadRequestException(INVALID_COUPON_POINT); + } + + return point; + } + + private int validateStock(int stock) { + if (stock < 0) { + throw new BadRequestException(INVALID_COUPON_STOCK); + } + + return stock; + } +} diff --git a/src/main/java/com/moabam/api/domain/entity/CouponWallet.java b/src/main/java/com/moabam/api/domain/entity/CouponWallet.java new file mode 100644 index 00000000..b8f3a6a2 --- /dev/null +++ b/src/main/java/com/moabam/api/domain/entity/CouponWallet.java @@ -0,0 +1,44 @@ +package com.moabam.api.domain.entity; + +import static java.util.Objects.*; + +import com.moabam.global.common.entity.BaseTimeEntity; + +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 jakarta.persistence.Table; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Entity +@Getter +@Table(name = "coupon_wallet") +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class CouponWallet extends BaseTimeEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "id") + private Long id; + + @Column(name = "member_id", nullable = false, updatable = false) + private Long memberId; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "coupon_id", nullable = false, updatable = false) + private Coupon coupon; + + @Builder + private CouponWallet(Long memberId, Coupon coupon) { + this.memberId = requireNonNull(memberId); + this.coupon = requireNonNull(coupon); + } +} diff --git a/src/main/java/com/moabam/api/domain/entity/enums/CouponType.java b/src/main/java/com/moabam/api/domain/entity/enums/CouponType.java new file mode 100644 index 00000000..9d49dd66 --- /dev/null +++ b/src/main/java/com/moabam/api/domain/entity/enums/CouponType.java @@ -0,0 +1,8 @@ +package com.moabam.api.domain.entity.enums; + +public enum CouponType { + MORNING_COUPON, + NIGHT_COUPON, + GOLDEN_COUPON, + DISCOUNT_COUPON +} diff --git a/src/main/java/com/moabam/global/error/model/ErrorMessage.java b/src/main/java/com/moabam/global/error/model/ErrorMessage.java index a5ee589a..f68f6573 100644 --- a/src/main/java/com/moabam/global/error/model/ErrorMessage.java +++ b/src/main/java/com/moabam/global/error/model/ErrorMessage.java @@ -39,7 +39,10 @@ public enum ErrorMessage { FAILED_FCM_INIT("파이어베이스 설정을 실패했습니다."), NOT_FOUND_FCM_TOKEN("해당 유저는 접속 중이 아닙니다."), - CONFLICT_KNOCK("이미 콕 알림을 보낸 대상입니다."); + CONFLICT_KNOCK("이미 콕 알림을 보낸 대상입니다."), + + INVALID_COUPON_POINT("쿠폰의 보너스 포인트는 0 이상이어야 합니다."), + INVALID_COUPON_STOCK("쿠폰의 재고는 0 이상이어야 합니다."); private final String message; } From ffea54a7b748d7bec24c3d22835fcbd5d215a4fe Mon Sep 17 00:00:00 2001 From: HyuckJuneHong Date: Wed, 8 Nov 2023 16:33:15 +0900 Subject: [PATCH 02/10] =?UTF-8?q?test:=20Coupon=20Entity=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 --- .../moabam/api/domain/entity/CouponTest.java | 31 +++++++++++++++++++ .../moabam/support/fixture/CouponFixture.java | 20 ++++++++++++ 2 files changed, 51 insertions(+) create mode 100644 src/test/java/com/moabam/api/domain/entity/CouponTest.java create mode 100644 src/test/java/com/moabam/support/fixture/CouponFixture.java diff --git a/src/test/java/com/moabam/api/domain/entity/CouponTest.java b/src/test/java/com/moabam/api/domain/entity/CouponTest.java new file mode 100644 index 00000000..9de9f547 --- /dev/null +++ b/src/test/java/com/moabam/api/domain/entity/CouponTest.java @@ -0,0 +1,31 @@ +package com.moabam.api.domain.entity; + +import static org.assertj.core.api.Assertions.*; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import com.moabam.global.error.exception.BadRequestException; +import com.moabam.global.error.model.ErrorMessage; +import com.moabam.support.fixture.CouponFixture; + +class CouponTest { + + @DisplayName("쿠폰 보너스 포인트가 0보다 작을 때, - BadRequestException") + @Test + void coupon_validatePoint_Point_BadRequestException() { + // When& Then + assertThatThrownBy(() -> CouponFixture.coupon(-1, 0)) + .isInstanceOf(BadRequestException.class) + .hasMessage(ErrorMessage.INVALID_COUPON_POINT.getMessage()); + } + + @DisplayName("쿠폰 재고가 0보다 작을 때, - BadRequestException") + @Test + void coupon_validatePoint_Stock_BadRequestException() { + // When& Then + assertThatThrownBy(() -> CouponFixture.coupon(0, -1)) + .isInstanceOf(BadRequestException.class) + .hasMessage(ErrorMessage.INVALID_COUPON_STOCK.getMessage()); + } +} diff --git a/src/test/java/com/moabam/support/fixture/CouponFixture.java b/src/test/java/com/moabam/support/fixture/CouponFixture.java new file mode 100644 index 00000000..22e58b8e --- /dev/null +++ b/src/test/java/com/moabam/support/fixture/CouponFixture.java @@ -0,0 +1,20 @@ +package com.moabam.support.fixture; + +import java.time.LocalDateTime; + +import com.moabam.api.domain.entity.Coupon; +import com.moabam.api.domain.entity.enums.CouponType; + +public final class CouponFixture { + + public static Coupon coupon(int point, int stock) { + return Coupon.builder() + .name("couponName") + .point(point) + .type(CouponType.MORNING_COUPON) + .stock(stock) + .startAt(LocalDateTime.now()) + .endAt(LocalDateTime.now()) + .build(); + } +} From 817abd1cf9aabfce68e7e6da064b07b03c5728f5 Mon Sep 17 00:00:00 2001 From: HyuckJuneHong Date: Wed, 8 Nov 2023 22:58:55 +0900 Subject: [PATCH 03/10] =?UTF-8?q?refactor:=20=EC=B4=88=EA=B8=B0=EA=B0=92?= =?UTF-8?q?=200=EC=97=90=EC=84=9C=201=EB=A1=9C=20=EC=A7=80=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/moabam/api/domain/entity/Coupon.java | 12 ++++++------ .../com/moabam/api/domain/entity/CouponTest.java | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/moabam/api/domain/entity/Coupon.java b/src/main/java/com/moabam/api/domain/entity/Coupon.java index 3dcfa9b1..a1a0ad31 100644 --- a/src/main/java/com/moabam/api/domain/entity/Coupon.java +++ b/src/main/java/com/moabam/api/domain/entity/Coupon.java @@ -35,21 +35,21 @@ public class Coupon extends BaseTimeEntity { @Column(name = "id") private Long id; - @Column(name = "name", nullable = false, unique = true) + @Column(name = "name", nullable = false, unique = true, length = 20) private String name; - @ColumnDefault("0") + @ColumnDefault("1") @Column(name = "point", nullable = false) private int point; - @Column(name = "description") + @Column(name = "description", length = 50) private String description; @Enumerated(value = EnumType.STRING) @Column(name = "type", nullable = false) private CouponType type; - @ColumnDefault("0") + @ColumnDefault("1") @Column(name = "stock", nullable = false) private int stock; @@ -72,7 +72,7 @@ private Coupon(String name, int point, String description, CouponType type, int } private int validatePoint(int point) { - if (point < 0) { + if (point < 1) { throw new BadRequestException(INVALID_COUPON_POINT); } @@ -80,7 +80,7 @@ private int validatePoint(int point) { } private int validateStock(int stock) { - if (stock < 0) { + if (stock < 1) { throw new BadRequestException(INVALID_COUPON_STOCK); } diff --git a/src/test/java/com/moabam/api/domain/entity/CouponTest.java b/src/test/java/com/moabam/api/domain/entity/CouponTest.java index 9de9f547..e19bfa23 100644 --- a/src/test/java/com/moabam/api/domain/entity/CouponTest.java +++ b/src/test/java/com/moabam/api/domain/entity/CouponTest.java @@ -15,7 +15,7 @@ class CouponTest { @Test void coupon_validatePoint_Point_BadRequestException() { // When& Then - assertThatThrownBy(() -> CouponFixture.coupon(-1, 0)) + assertThatThrownBy(() -> CouponFixture.coupon(0, 1)) .isInstanceOf(BadRequestException.class) .hasMessage(ErrorMessage.INVALID_COUPON_POINT.getMessage()); } @@ -24,7 +24,7 @@ void coupon_validatePoint_Point_BadRequestException() { @Test void coupon_validatePoint_Stock_BadRequestException() { // When& Then - assertThatThrownBy(() -> CouponFixture.coupon(0, -1)) + assertThatThrownBy(() -> CouponFixture.coupon(1, 0)) .isInstanceOf(BadRequestException.class) .hasMessage(ErrorMessage.INVALID_COUPON_STOCK.getMessage()); } From a22f382ff1bc3e4c9398626951b0ae667476c6ba Mon Sep 17 00:00:00 2001 From: HyuckJuneHong Date: Wed, 8 Nov 2023 23:41:03 +0900 Subject: [PATCH 04/10] =?UTF-8?q?feat:=20=EC=BF=A0=ED=8F=B0=20=EC=A2=85?= =?UTF-8?q?=EB=A5=98=EC=97=90=20=EB=8C=80=ED=95=9C=20=EC=A1=B0=ED=9A=8C=20?= =?UTF-8?q?=EC=B2=98=EB=A6=AC=20=EA=B5=AC=ED=98=84=20=EB=B0=8F=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 --- .../api/domain/entity/enums/CouponType.java | 38 +++++++++++++++++-- .../domain/entity/enums/CouponTypeTest.java | 31 +++++++++++++++ 2 files changed, 65 insertions(+), 4 deletions(-) create mode 100644 src/test/java/com/moabam/api/domain/entity/enums/CouponTypeTest.java diff --git a/src/main/java/com/moabam/api/domain/entity/enums/CouponType.java b/src/main/java/com/moabam/api/domain/entity/enums/CouponType.java index 9d49dd66..9cdb78de 100644 --- a/src/main/java/com/moabam/api/domain/entity/enums/CouponType.java +++ b/src/main/java/com/moabam/api/domain/entity/enums/CouponType.java @@ -1,8 +1,38 @@ package com.moabam.api.domain.entity.enums; +import java.util.Arrays; +import java.util.Collections; +import java.util.Map; +import java.util.Optional; +import java.util.function.Function; +import java.util.stream.Collectors; + +import com.moabam.global.error.exception.NotFoundException; +import com.moabam.global.error.model.ErrorMessage; + +import lombok.AccessLevel; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor(access = AccessLevel.PRIVATE) public enum CouponType { - MORNING_COUPON, - NIGHT_COUPON, - GOLDEN_COUPON, - DISCOUNT_COUPON + + MORNING_COUPON("아침"), + NIGHT_COUPON("저녁"), + GOLDEN_COUPON("황금"), + DISCOUNT_COUPON("할인"); + + private final String typeName; + private static final Map COUPON_TYPE_MAP; + + static { + COUPON_TYPE_MAP = Collections.unmodifiableMap(Arrays.stream(values()) + .collect(Collectors.toMap(CouponType::getTypeName, Function.identity()))); + } + + public static CouponType from(String typeName) { + return Optional.ofNullable(COUPON_TYPE_MAP.get(typeName)) + .orElseThrow(() -> new NotFoundException(ErrorMessage.NOT_FOUND_COUPON_TYPE)); + } } diff --git a/src/test/java/com/moabam/api/domain/entity/enums/CouponTypeTest.java b/src/test/java/com/moabam/api/domain/entity/enums/CouponTypeTest.java new file mode 100644 index 00000000..79978835 --- /dev/null +++ b/src/test/java/com/moabam/api/domain/entity/enums/CouponTypeTest.java @@ -0,0 +1,31 @@ +package com.moabam.api.domain.entity.enums; + +import static org.assertj.core.api.Assertions.*; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import com.moabam.global.error.exception.NotFoundException; +import com.moabam.global.error.model.ErrorMessage; + +class CouponTypeTest { + + @DisplayName("존재하는 쿠폰을 가져오려고 할 때, - CouponType") + @Test + void couponType_from() { + // When + CouponType actual = CouponType.from("황금"); + + // Then + assertThat(actual).isEqualTo(CouponType.GOLDEN_COUPON); + } + + @DisplayName("존재하지 않는 쿠폰을 가져오려고 할 때, - NotFoundException") + @Test + void couponType_from_NotFoundException() { + // When & Then + assertThatThrownBy(() -> CouponType.from("Not-Coupon")) + .isInstanceOf(NotFoundException.class) + .hasMessage(ErrorMessage.NOT_FOUND_COUPON_TYPE.getMessage()); + } +} From 13c8cccfcc0ac6c35c9560d8acddfc65c181c550 Mon Sep 17 00:00:00 2001 From: HyuckJuneHong Date: Wed, 8 Nov 2023 23:41:35 +0900 Subject: [PATCH 05/10] =?UTF-8?q?refactor:=20=EC=BF=A0=ED=8F=B0=20?= =?UTF-8?q?=EC=BB=AC=EB=9F=BC=EC=9C=BC=EB=A1=9C=20=EA=B4=80=EB=A6=AC?= =?UTF-8?q?=EC=9E=90=20=EC=95=84=EC=9D=B4=EB=94=94=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/com/moabam/api/domain/entity/Coupon.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/moabam/api/domain/entity/Coupon.java b/src/main/java/com/moabam/api/domain/entity/Coupon.java index a1a0ad31..102da46f 100644 --- a/src/main/java/com/moabam/api/domain/entity/Coupon.java +++ b/src/main/java/com/moabam/api/domain/entity/Coupon.java @@ -59,9 +59,12 @@ public class Coupon extends BaseTimeEntity { @Column(name = "end_at", nullable = false) private LocalDateTime endAt; + @Column(name = "admin_id", updatable = false, nullable = false) + private Long adminId; + @Builder private Coupon(String name, int point, String description, CouponType type, int stock, LocalDateTime startAt, - LocalDateTime endAt) { + LocalDateTime endAt, Long adminId) { this.name = requireNonNull(name); this.point = validatePoint(point); this.description = description; @@ -69,6 +72,7 @@ private Coupon(String name, int point, String description, CouponType type, int this.stock = validateStock(stock); this.startAt = requireNonNull(startAt); this.endAt = requireNonNull(endAt); + this.adminId = requireNonNull(adminId); } private int validatePoint(int point) { From 704777f2c9dc755d3699f166c46a32ba6e5af8c5 Mon Sep 17 00:00:00 2001 From: HyuckJuneHong Date: Wed, 8 Nov 2023 23:42:28 +0900 Subject: [PATCH 06/10] =?UTF-8?q?feat:=20=EA=B4=80=EB=A6=AC=EC=9E=90?= =?UTF-8?q?=EC=9D=98=20=EC=BF=A0=ED=8F=B0=20=EC=83=9D=EC=84=B1=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../moabam/api/application/CouponService.java | 45 +++++++++++++++++++ .../domain/repository/CouponRepository.java | 10 +++++ .../java/com/moabam/api/dto/CouponMapper.java | 24 ++++++++++ .../moabam/api/dto/CreateCouponRequest.java | 25 +++++++++++ .../api/presentation/CouponController.java | 24 ++++++++++ .../global/error/model/ErrorMessage.java | 5 ++- 6 files changed, 132 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/moabam/api/application/CouponService.java create mode 100644 src/main/java/com/moabam/api/domain/repository/CouponRepository.java create mode 100644 src/main/java/com/moabam/api/dto/CouponMapper.java create mode 100644 src/main/java/com/moabam/api/dto/CreateCouponRequest.java create mode 100644 src/main/java/com/moabam/api/presentation/CouponController.java diff --git a/src/main/java/com/moabam/api/application/CouponService.java b/src/main/java/com/moabam/api/application/CouponService.java new file mode 100644 index 00000000..7f8609bd --- /dev/null +++ b/src/main/java/com/moabam/api/application/CouponService.java @@ -0,0 +1,45 @@ +package com.moabam.api.application; + +import java.time.LocalDateTime; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.moabam.api.domain.entity.Coupon; +import com.moabam.api.domain.repository.CouponRepository; +import com.moabam.api.dto.CouponMapper; +import com.moabam.api.dto.CreateCouponRequest; +import com.moabam.global.error.exception.BadRequestException; +import com.moabam.global.error.exception.ConflictException; +import com.moabam.global.error.model.ErrorMessage; + +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +@Transactional(readOnly = true) +public class CouponService { + + private final CouponRepository couponRepository; + + @Transactional + public void createCoupon(Long adminId, CreateCouponRequest request) { + validateConflictCouponName(request.name()); + validateCouponPeriod(request.startAt(), request.endAt()); + + Coupon coupon = CouponMapper.toEntity(adminId, request); + couponRepository.save(coupon); + } + + private void validateConflictCouponName(String name) { + if (couponRepository.existsByName(name)) { + throw new ConflictException(ErrorMessage.CONFLICT_COUPON_NAME); + } + } + + private void validateCouponPeriod(LocalDateTime startAt, LocalDateTime endAt) { + if (startAt.isAfter(endAt)) { + throw new BadRequestException(ErrorMessage.INVALID_COUPON_PERIOD); + } + } +} diff --git a/src/main/java/com/moabam/api/domain/repository/CouponRepository.java b/src/main/java/com/moabam/api/domain/repository/CouponRepository.java new file mode 100644 index 00000000..1a262050 --- /dev/null +++ b/src/main/java/com/moabam/api/domain/repository/CouponRepository.java @@ -0,0 +1,10 @@ +package com.moabam.api.domain.repository; + +import org.springframework.data.jpa.repository.JpaRepository; + +import com.moabam.api.domain.entity.Coupon; + +public interface CouponRepository extends JpaRepository { + + boolean existsByName(String name); +} diff --git a/src/main/java/com/moabam/api/dto/CouponMapper.java b/src/main/java/com/moabam/api/dto/CouponMapper.java new file mode 100644 index 00000000..400f232d --- /dev/null +++ b/src/main/java/com/moabam/api/dto/CouponMapper.java @@ -0,0 +1,24 @@ +package com.moabam.api.dto; + +import com.moabam.api.domain.entity.Coupon; +import com.moabam.api.domain.entity.enums.CouponType; + +import lombok.AccessLevel; +import lombok.NoArgsConstructor; + +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public final class CouponMapper { + + public static Coupon toEntity(Long adminId, CreateCouponRequest request) { + return Coupon.builder() + .name(request.name()) + .description(request.description()) + .type(CouponType.from(request.type())) + .point(request.point()) + .stock(request.stock()) + .startAt(request.startAt()) + .endAt(request.endAt()) + .adminId(adminId) + .build(); + } +} diff --git a/src/main/java/com/moabam/api/dto/CreateCouponRequest.java b/src/main/java/com/moabam/api/dto/CreateCouponRequest.java new file mode 100644 index 00000000..289ebcf1 --- /dev/null +++ b/src/main/java/com/moabam/api/dto/CreateCouponRequest.java @@ -0,0 +1,25 @@ +package com.moabam.api.dto; + +import java.time.LocalDateTime; + +import org.hibernate.validator.constraints.Length; + +import com.fasterxml.jackson.annotation.JsonFormat; + +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; + +public record CreateCouponRequest( + @NotBlank(message = "쿠폰명이 입력되지 않았거나 20자를 넘었습니다.") @Length(max = 20) String name, + @Length(max = 50, message = "쿠폰 간단 소개는 최대 50자까지 가능합니다.") String description, + @NotBlank(message = "쿠폰 종류를 입력해주세요.") String type, + @Min(value = 1, message = "벌레 수 혹은 할인 금액은 1 이상이어야 합니다.") int point, + @Min(value = 1, message = "쿠폰 재고는 1 이상이어야 합니다.") int stock, + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm") + @NotNull(message = "쿠폰 발급 시작 시각을 입력해주세요.") LocalDateTime startAt, + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm") + @NotNull(message = "쿠폰 발급 종료 시각을 입력해주세요.") LocalDateTime endAt +) { + +} diff --git a/src/main/java/com/moabam/api/presentation/CouponController.java b/src/main/java/com/moabam/api/presentation/CouponController.java new file mode 100644 index 00000000..e984cc29 --- /dev/null +++ b/src/main/java/com/moabam/api/presentation/CouponController.java @@ -0,0 +1,24 @@ +package com.moabam.api.presentation; + +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.moabam.api.application.CouponService; +import com.moabam.api.dto.CreateCouponRequest; + +import lombok.RequiredArgsConstructor; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/admins/coupons") +public class CouponController { + + private final CouponService couponService; + + @PostMapping + public void createCoupon(@RequestBody CreateCouponRequest request) { + couponService.createCoupon(1L, request); + } +} diff --git a/src/main/java/com/moabam/global/error/model/ErrorMessage.java b/src/main/java/com/moabam/global/error/model/ErrorMessage.java index f68f6573..c5843d25 100644 --- a/src/main/java/com/moabam/global/error/model/ErrorMessage.java +++ b/src/main/java/com/moabam/global/error/model/ErrorMessage.java @@ -42,7 +42,10 @@ public enum ErrorMessage { CONFLICT_KNOCK("이미 콕 알림을 보낸 대상입니다."), INVALID_COUPON_POINT("쿠폰의 보너스 포인트는 0 이상이어야 합니다."), - INVALID_COUPON_STOCK("쿠폰의 재고는 0 이상이어야 합니다."); + INVALID_COUPON_STOCK("쿠폰의 재고는 0 이상이어야 합니다."), + CONFLICT_COUPON_NAME("쿠폰의 이름이 중복되었습니다."), + NOT_FOUND_COUPON_TYPE("존재하지 않는 쿠폰 종류입니다."), + INVALID_COUPON_PERIOD("쿠폰 발급 종료 시각은 시작 시각보다 이후여야 합니다."); private final String message; } From d40b614eecae8d14d3148eb5c4c987deb9f02b5f Mon Sep 17 00:00:00 2001 From: HyuckJuneHong Date: Thu, 9 Nov 2023 03:26:58 +0900 Subject: [PATCH 07/10] =?UTF-8?q?test:=20=EC=BF=A0=ED=8F=B0=20=EB=B0=9C?= =?UTF-8?q?=ED=96=89=20=EA=B8=B0=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 --- src/docs/asciidoc/coupon.adoc | 35 ++ .../moabam/api/dto/CreateCouponRequest.java | 2 + .../api/presentation/CouponController.java | 3 + src/main/resources/static/docs/coupon.html | 540 ++++++++++++++++++ .../api/application/CouponServiceTest.java | 89 +++ .../moabam/api/domain/entity/CouponTest.java | 4 +- .../domain/entity/enums/CouponTypeTest.java | 4 +- .../api/dto/CreateCouponRequestTest.java | 31 + .../presentation/CouponControllerTest.java | 80 +++ .../moabam/support/fixture/CouponFixture.java | 13 + .../support/fixture/CouponSnippetFixture.java | 19 + 11 files changed, 816 insertions(+), 4 deletions(-) create mode 100644 src/docs/asciidoc/coupon.adoc create mode 100644 src/main/resources/static/docs/coupon.html create mode 100644 src/test/java/com/moabam/api/application/CouponServiceTest.java create mode 100644 src/test/java/com/moabam/api/dto/CreateCouponRequestTest.java create mode 100644 src/test/java/com/moabam/api/presentation/CouponControllerTest.java create mode 100644 src/test/java/com/moabam/support/fixture/CouponSnippetFixture.java diff --git a/src/docs/asciidoc/coupon.adoc b/src/docs/asciidoc/coupon.adoc new file mode 100644 index 00000000..f06a91ef --- /dev/null +++ b/src/docs/asciidoc/coupon.adoc @@ -0,0 +1,35 @@ +== 쿠폰(Coupon) + + 쿠폰에 대해 생성/삭제/조회/발급/사용 기능을 제공합니다. + +=== 쿠폰 생성 + + 관리자가 쿠폰을 생성합니다. + +[discrete] +==== 요청 + +include::{snippets}/coupons/http-request.adoc[] + +[discrete] +==== 응답 + +include::{snippets}/coupons/http-response.adoc[] + +=== 쿠폰 삭제 (진행 중) + + 관리자가 쿠폰을 삭제합니다. + +=== 쿠폰 조회 (진행 중) + + 관리자 혹은 사용자가 쿠폰들을 조회합니다. + + 사용자가 자신의 보관함에 있는 쿠폰들을 조회합니다. + +=== 쿠폰 발급 (진행 중) + + 사용자가 발급 가능한 쿠폰을 선착순으로 발급 받습니다. + +=== 쿠폰 사용 (진행 중) + + 사용자가 자신의 보관함에 있는 쿠폰들을 사용합니다. diff --git a/src/main/java/com/moabam/api/dto/CreateCouponRequest.java b/src/main/java/com/moabam/api/dto/CreateCouponRequest.java index 289ebcf1..710fffc3 100644 --- a/src/main/java/com/moabam/api/dto/CreateCouponRequest.java +++ b/src/main/java/com/moabam/api/dto/CreateCouponRequest.java @@ -9,7 +9,9 @@ import jakarta.validation.constraints.Min; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; +import lombok.Builder; +@Builder public record CreateCouponRequest( @NotBlank(message = "쿠폰명이 입력되지 않았거나 20자를 넘었습니다.") @Length(max = 20) String name, @Length(max = 50, message = "쿠폰 간단 소개는 최대 50자까지 가능합니다.") String description, diff --git a/src/main/java/com/moabam/api/presentation/CouponController.java b/src/main/java/com/moabam/api/presentation/CouponController.java index e984cc29..acac1ac8 100644 --- a/src/main/java/com/moabam/api/presentation/CouponController.java +++ b/src/main/java/com/moabam/api/presentation/CouponController.java @@ -1,8 +1,10 @@ package com.moabam.api.presentation; +import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestController; import com.moabam.api.application.CouponService; @@ -18,6 +20,7 @@ public class CouponController { private final CouponService couponService; @PostMapping + @ResponseStatus(HttpStatus.OK) public void createCoupon(@RequestBody CreateCouponRequest request) { couponService.createCoupon(1L, request); } diff --git a/src/main/resources/static/docs/coupon.html b/src/main/resources/static/docs/coupon.html new file mode 100644 index 00000000..c6daacf7 --- /dev/null +++ b/src/main/resources/static/docs/coupon.html @@ -0,0 +1,540 @@ + + + + + + + +쿠폰(Coupon) + + + + + +
+
+

쿠폰(Coupon)

+
+
+
+
쿠폰에 대해 생성/삭제/조회/발급/사용 기능을 제공합니다.
+
+
+
+

쿠폰 생성

+
+
+
관리자가 쿠폰을 생성합니다.
+
+
+

요청

+
+
+
POST /admins/coupons HTTP/1.1
+Content-Type: application/json;charset=UTF-8
+Content-Length: 186
+Host: localhost:8080
+
+{
+  "name" : "couponName",
+  "description" : "coupon description",
+  "type" : "황금",
+  "point" : 10,
+  "stock" : 10,
+  "startAt" : "2000-01-22T10:30",
+  "endAt" : "2000-02-22T11:00"
+}
+
+
+

응답

+
+
+
HTTP/1.1 409 Conflict
+Vary: Origin
+Vary: Access-Control-Request-Method
+Vary: Access-Control-Request-Headers
+Content-Type: application/json
+Content-Length: 62
+
+{
+  "message" : "쿠폰의 이름이 중복되었습니다."
+}
+
+
+
+
+

쿠폰 삭제 (진행 중)

+
+
+
관리자가 쿠폰을 삭제합니다.
+
+
+
+
+

쿠폰 조회 (진행 중)

+
+
+
관리자 혹은 사용자가 쿠폰들을 조회합니다.
+
+
+
+
+
사용자가 자신의 보관함에 있는 쿠폰들을 조회합니다.
+
+
+
+
+

쿠폰 발급 (진행 중)

+
+
+
사용자가 발급 가능한 쿠폰을 선착순으로 발급 받습니다.
+
+
+
+
+

쿠폰 사용 (진행 중)

+
+
+
사용자가 자신의 보관함에 있는 쿠폰들을 사용합니다.
+
+
+
+
+
+
+ + + \ No newline at end of file diff --git a/src/test/java/com/moabam/api/application/CouponServiceTest.java b/src/test/java/com/moabam/api/application/CouponServiceTest.java new file mode 100644 index 00000000..2759bec5 --- /dev/null +++ b/src/test/java/com/moabam/api/application/CouponServiceTest.java @@ -0,0 +1,89 @@ +package com.moabam.api.application; + +import static org.assertj.core.api.Assertions.*; +import static org.mockito.BDDMockito.*; + +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 com.moabam.api.domain.entity.Coupon; +import com.moabam.api.domain.entity.enums.CouponType; +import com.moabam.api.domain.repository.CouponRepository; +import com.moabam.api.dto.CreateCouponRequest; +import com.moabam.global.error.exception.BadRequestException; +import com.moabam.global.error.exception.ConflictException; +import com.moabam.global.error.exception.NotFoundException; +import com.moabam.global.error.model.ErrorMessage; +import com.moabam.support.fixture.CouponFixture; + +@ExtendWith(MockitoExtension.class) +class CouponServiceTest { + + @InjectMocks + private CouponService couponService; + + @Mock + private CouponRepository couponRepository; + + @DisplayName("쿠폰을 성공적으로 발행한다. - Void") + @Test + void couponService_createCoupon() { + // Given + String couponType = CouponType.GOLDEN_COUPON.getTypeName(); + CreateCouponRequest request = CouponFixture.createCouponRequest(couponType, 1, 2); + + given(couponRepository.existsByName(any(String.class))).willReturn(false); + + // When + couponService.createCoupon(1L, request); + + // Then + verify(couponRepository).save(any(Coupon.class)); + } + + @DisplayName("중복된 쿠폰명을 발행한다. - ConflictException") + @Test + void couponService_createCoupon_ConflictException() { + // Given + String couponType = CouponType.GOLDEN_COUPON.getTypeName(); + CreateCouponRequest request = CouponFixture.createCouponRequest(couponType, 1, 2); + + given(couponRepository.existsByName(any(String.class))).willReturn(true); + + // When & Then + assertThatThrownBy(() -> couponService.createCoupon(1L, request)) + .isInstanceOf(ConflictException.class) + .hasMessage(ErrorMessage.CONFLICT_COUPON_NAME.getMessage()); + } + + @DisplayName("존재하지 않는 쿠폰 종류를 발행한다. - NotFoundException") + @Test + void couponService_createCoupon_NotFoundException() { + // Given + CreateCouponRequest request = CouponFixture.createCouponRequest("UNKNOWN", 1, 2); + given(couponRepository.existsByName(any(String.class))).willReturn(false); + + // When & Then + assertThatThrownBy(() -> couponService.createCoupon(1L, request)) + .isInstanceOf(NotFoundException.class) + .hasMessage(ErrorMessage.NOT_FOUND_COUPON_TYPE.getMessage()); + } + + @DisplayName("쿠폰 발급 종료 기간이 시작 기간보다 더 이전인 쿠폰을 발행한다. - BadRequestException") + @Test + void couponService_createCoupon_BadRequestException() { + // Given + String couponType = CouponType.GOLDEN_COUPON.getTypeName(); + CreateCouponRequest request = CouponFixture.createCouponRequest(couponType, 2, 1); + given(couponRepository.existsByName(any(String.class))).willReturn(false); + + // When & Then + assertThatThrownBy(() -> couponService.createCoupon(1L, request)) + .isInstanceOf(BadRequestException.class) + .hasMessage(ErrorMessage.INVALID_COUPON_PERIOD.getMessage()); + } +} diff --git a/src/test/java/com/moabam/api/domain/entity/CouponTest.java b/src/test/java/com/moabam/api/domain/entity/CouponTest.java index e19bfa23..4d5faadd 100644 --- a/src/test/java/com/moabam/api/domain/entity/CouponTest.java +++ b/src/test/java/com/moabam/api/domain/entity/CouponTest.java @@ -11,7 +11,7 @@ class CouponTest { - @DisplayName("쿠폰 보너스 포인트가 0보다 작을 때, - BadRequestException") + @DisplayName("쿠폰 보너스 포인트가 1보다 작다. - BadRequestException") @Test void coupon_validatePoint_Point_BadRequestException() { // When& Then @@ -20,7 +20,7 @@ void coupon_validatePoint_Point_BadRequestException() { .hasMessage(ErrorMessage.INVALID_COUPON_POINT.getMessage()); } - @DisplayName("쿠폰 재고가 0보다 작을 때, - BadRequestException") + @DisplayName("쿠폰 재고가 1보다 작다. - BadRequestException") @Test void coupon_validatePoint_Stock_BadRequestException() { // When& Then diff --git a/src/test/java/com/moabam/api/domain/entity/enums/CouponTypeTest.java b/src/test/java/com/moabam/api/domain/entity/enums/CouponTypeTest.java index 79978835..4ceed56f 100644 --- a/src/test/java/com/moabam/api/domain/entity/enums/CouponTypeTest.java +++ b/src/test/java/com/moabam/api/domain/entity/enums/CouponTypeTest.java @@ -10,7 +10,7 @@ class CouponTypeTest { - @DisplayName("존재하는 쿠폰을 가져오려고 할 때, - CouponType") + @DisplayName("존재하는 쿠폰을 가져온다. - CouponType") @Test void couponType_from() { // When @@ -20,7 +20,7 @@ void couponType_from() { assertThat(actual).isEqualTo(CouponType.GOLDEN_COUPON); } - @DisplayName("존재하지 않는 쿠폰을 가져오려고 할 때, - NotFoundException") + @DisplayName("존재하지 않는 쿠폰을 가져온다. - NotFoundException") @Test void couponType_from_NotFoundException() { // When & Then diff --git a/src/test/java/com/moabam/api/dto/CreateCouponRequestTest.java b/src/test/java/com/moabam/api/dto/CreateCouponRequestTest.java new file mode 100644 index 00000000..18d2c481 --- /dev/null +++ b/src/test/java/com/moabam/api/dto/CreateCouponRequestTest.java @@ -0,0 +1,31 @@ +package com.moabam.api.dto; + +import static org.assertj.core.api.Assertions.*; + +import java.time.LocalDateTime; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; + +class CreateCouponRequestTest { + + @DisplayName("쿠폰 발급 가능 시작 날짜가 올바른 형식으로 입력된다. - yyyy-MM-dd'T'HH:mm") + @Test + void createCouponRequest_StartAt() throws JsonProcessingException { + // Given + ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.registerModule(new JavaTimeModule()); + + String json = "{\"startAt\":\"2023-11-09T10:10\"}"; + + // When + CreateCouponRequest actual = objectMapper.readValue(json, CreateCouponRequest.class); + + // Then + assertThat(actual.startAt()).isEqualTo(LocalDateTime.of(2023, 11, 9, 10, 10)); + } +} diff --git a/src/test/java/com/moabam/api/presentation/CouponControllerTest.java b/src/test/java/com/moabam/api/presentation/CouponControllerTest.java new file mode 100644 index 00000000..215e0b85 --- /dev/null +++ b/src/test/java/com/moabam/api/presentation/CouponControllerTest.java @@ -0,0 +1,80 @@ +package com.moabam.api.presentation; + +import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.*; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.*; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +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.restdocs.AutoConfigureRestDocs; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.transaction.annotation.Transactional; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.moabam.api.domain.entity.enums.CouponType; +import com.moabam.api.domain.repository.CouponRepository; +import com.moabam.api.dto.CouponMapper; +import com.moabam.api.dto.CreateCouponRequest; +import com.moabam.support.fixture.CouponFixture; +import com.moabam.support.fixture.CouponSnippetFixture; + +@Transactional +@SpringBootTest +@AutoConfigureMockMvc +@AutoConfigureRestDocs +class CouponControllerTest { + + @Autowired + private MockMvc mockMvc; + + @Autowired + private ObjectMapper objectMapper; + + @Autowired + private CouponRepository couponRepository; + + @DisplayName("쿠폰을 성공적으로 발행한다. - Void") + @Test + void couponController_createCoupon() throws Exception { + // Given + String couponType = CouponType.GOLDEN_COUPON.getTypeName(); + CreateCouponRequest request = CouponFixture.createCouponRequest(couponType, 1, 2); + + // When & Then + mockMvc.perform(post("/admins/coupons") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(request))) + .andDo(print()) + .andDo(document("coupons", + preprocessRequest(prettyPrint()), + preprocessResponse(prettyPrint()), + CouponSnippetFixture.CREATE_COUPON_REQUEST)) + .andExpect(status().isOk()); + } + + @DisplayName("쿠폰명이 중복된 쿠폰을 발행한다. - ConflictException") + @Test + void couponController_createCoupon_ConflictException() throws Exception { + // Given + String couponType = CouponType.GOLDEN_COUPON.getTypeName(); + CreateCouponRequest request = CouponFixture.createCouponRequest(couponType, 1, 2); + couponRepository.save(CouponMapper.toEntity(1L, request)); + + // When & Then + mockMvc.perform(post("/admins/coupons") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(request))) + .andDo(print()) + .andDo(document("coupons", + preprocessRequest(prettyPrint()), + preprocessResponse(prettyPrint()), + CouponSnippetFixture.CREATE_COUPON_REQUEST)) + .andExpect(status().isConflict()); + } +} diff --git a/src/test/java/com/moabam/support/fixture/CouponFixture.java b/src/test/java/com/moabam/support/fixture/CouponFixture.java index 22e58b8e..5b4e8e9b 100644 --- a/src/test/java/com/moabam/support/fixture/CouponFixture.java +++ b/src/test/java/com/moabam/support/fixture/CouponFixture.java @@ -4,6 +4,7 @@ import com.moabam.api.domain.entity.Coupon; import com.moabam.api.domain.entity.enums.CouponType; +import com.moabam.api.dto.CreateCouponRequest; public final class CouponFixture { @@ -17,4 +18,16 @@ public static Coupon coupon(int point, int stock) { .endAt(LocalDateTime.now()) .build(); } + + public static CreateCouponRequest createCouponRequest(String couponType, int startMonth, int endMonth) { + return CreateCouponRequest.builder() + .name("couponName") + .description("coupon description") + .point(10) + .type(couponType) + .stock(10) + .startAt(LocalDateTime.of(2000, startMonth, 22, 10, 30, 0)) + .endAt(LocalDateTime.of(2000, endMonth, 22, 11, 0, 0)) + .build(); + } } diff --git a/src/test/java/com/moabam/support/fixture/CouponSnippetFixture.java b/src/test/java/com/moabam/support/fixture/CouponSnippetFixture.java new file mode 100644 index 00000000..92345c0e --- /dev/null +++ b/src/test/java/com/moabam/support/fixture/CouponSnippetFixture.java @@ -0,0 +1,19 @@ +package com.moabam.support.fixture; + +import static org.springframework.restdocs.payload.JsonFieldType.*; +import static org.springframework.restdocs.payload.PayloadDocumentation.*; + +import org.springframework.restdocs.payload.RequestFieldsSnippet; + +public final class CouponSnippetFixture { + + public static final RequestFieldsSnippet CREATE_COUPON_REQUEST = requestFields( + fieldWithPath("name").type(STRING).description("쿠폰명"), + fieldWithPath("description").type(STRING).description("쿠폰 간단 소개 (NULL 가능)"), + fieldWithPath("type").type(STRING).description("쿠폰 종류 (아침, 저녁, 황금, 할인)"), + fieldWithPath("point").type(NUMBER).description("쿠폰 사용 시, 제공하는 포인트량"), + fieldWithPath("stock").type(NUMBER).description("쿠폰을 발급 받을 수 있는 수"), + fieldWithPath("startAt").type(STRING).description("쿠폰 발급 시작 날짜 (Ex: yyyy-MM-dd'T'HH:mm)"), + fieldWithPath("endAt").type(STRING).description("쿠폰 발급 종료 날짜 (Ex: yyyy-MM-dd'T'HH:mm)") + ); +} From 923b2ecdb8c1304c91bf035d4e420380e72ac2f8 Mon Sep 17 00:00:00 2001 From: HyuckJuneHong Date: Thu, 9 Nov 2023 03:46:27 +0900 Subject: [PATCH 08/10] =?UTF-8?q?test:=20=EC=BF=A0=ED=8F=B0=20=EC=97=94?= =?UTF-8?q?=ED=8B=B0=ED=8B=B0=20=ED=85=8C=EC=8A=A4=ED=8A=B8=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 --- .../com/moabam/api/domain/entity/Coupon.java | 2 +- .../api/domain/entity/CouponWallet.java | 44 ------------------- .../moabam/api/domain/entity/CouponTest.java | 32 ++++++++++++++ .../moabam/support/fixture/CouponFixture.java | 5 ++- 4 files changed, 36 insertions(+), 47 deletions(-) delete mode 100644 src/main/java/com/moabam/api/domain/entity/CouponWallet.java diff --git a/src/main/java/com/moabam/api/domain/entity/Coupon.java b/src/main/java/com/moabam/api/domain/entity/Coupon.java index 102da46f..4aaeb163 100644 --- a/src/main/java/com/moabam/api/domain/entity/Coupon.java +++ b/src/main/java/com/moabam/api/domain/entity/Coupon.java @@ -41,7 +41,7 @@ public class Coupon extends BaseTimeEntity { @ColumnDefault("1") @Column(name = "point", nullable = false) private int point; - + @Column(name = "description", length = 50) private String description; diff --git a/src/main/java/com/moabam/api/domain/entity/CouponWallet.java b/src/main/java/com/moabam/api/domain/entity/CouponWallet.java deleted file mode 100644 index b8f3a6a2..00000000 --- a/src/main/java/com/moabam/api/domain/entity/CouponWallet.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.moabam.api.domain.entity; - -import static java.util.Objects.*; - -import com.moabam.global.common.entity.BaseTimeEntity; - -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 jakarta.persistence.Table; -import lombok.AccessLevel; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Entity -@Getter -@Table(name = "coupon_wallet") -@NoArgsConstructor(access = AccessLevel.PROTECTED) -public class CouponWallet extends BaseTimeEntity { - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "id") - private Long id; - - @Column(name = "member_id", nullable = false, updatable = false) - private Long memberId; - - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "coupon_id", nullable = false, updatable = false) - private Coupon coupon; - - @Builder - private CouponWallet(Long memberId, Coupon coupon) { - this.memberId = requireNonNull(memberId); - this.coupon = requireNonNull(coupon); - } -} diff --git a/src/test/java/com/moabam/api/domain/entity/CouponTest.java b/src/test/java/com/moabam/api/domain/entity/CouponTest.java index 4d5faadd..3729a414 100644 --- a/src/test/java/com/moabam/api/domain/entity/CouponTest.java +++ b/src/test/java/com/moabam/api/domain/entity/CouponTest.java @@ -2,15 +2,47 @@ import static org.assertj.core.api.Assertions.*; +import java.time.LocalDateTime; + import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import com.moabam.api.domain.entity.enums.CouponType; import com.moabam.global.error.exception.BadRequestException; import com.moabam.global.error.model.ErrorMessage; import com.moabam.support.fixture.CouponFixture; class CouponTest { + @DisplayName("쿠폰이 정상적으로 생성된다. - Coupon") + @Test + void coupon() { + // Given + LocalDateTime startAt = LocalDateTime.of(2000, 1, 22, 10, 30, 0); + LocalDateTime endAt = LocalDateTime.of(2000, 1, 22, 11, 0, 0); + + // When + Coupon actual = Coupon.builder() + .name("couponName") + .point(10) + .type(CouponType.MORNING_COUPON) + .stock(100) + .startAt(startAt) + .endAt(endAt) + .adminId(1L) + .build(); + + // Then + assertThat(actual.getName()).isEqualTo("couponName"); + assertThat(actual.getDescription()).isEqualTo(null); + assertThat(actual.getPoint()).isEqualTo(10); + assertThat(actual.getStock()).isEqualTo(100); + assertThat(actual.getType()).isEqualTo(CouponType.MORNING_COUPON); + assertThat(actual.getStartAt()).isEqualTo(startAt); + assertThat(actual.getEndAt()).isEqualTo(endAt); + assertThat(actual.getAdminId()).isEqualTo(1L); + } + @DisplayName("쿠폰 보너스 포인트가 1보다 작다. - BadRequestException") @Test void coupon_validatePoint_Point_BadRequestException() { diff --git a/src/test/java/com/moabam/support/fixture/CouponFixture.java b/src/test/java/com/moabam/support/fixture/CouponFixture.java index 5b4e8e9b..6dbc68b8 100644 --- a/src/test/java/com/moabam/support/fixture/CouponFixture.java +++ b/src/test/java/com/moabam/support/fixture/CouponFixture.java @@ -14,8 +14,9 @@ public static Coupon coupon(int point, int stock) { .point(point) .type(CouponType.MORNING_COUPON) .stock(stock) - .startAt(LocalDateTime.now()) - .endAt(LocalDateTime.now()) + .startAt(LocalDateTime.of(2000, 1, 22, 10, 30, 0)) + .endAt(LocalDateTime.of(2000, 1, 22, 11, 0, 0)) + .adminId(1L) .build(); } From f0dd697ee74e101935a2b4bb2906741e01e72e8d Mon Sep 17 00:00:00 2001 From: HyuckJuneHong Date: Thu, 9 Nov 2023 03:47:22 +0900 Subject: [PATCH 09/10] =?UTF-8?q?style:=20test=20=EB=A9=94=EC=84=9C?= =?UTF-8?q?=EB=93=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/com/moabam/api/domain/entity/CouponTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/com/moabam/api/domain/entity/CouponTest.java b/src/test/java/com/moabam/api/domain/entity/CouponTest.java index 3729a414..1f68c7de 100644 --- a/src/test/java/com/moabam/api/domain/entity/CouponTest.java +++ b/src/test/java/com/moabam/api/domain/entity/CouponTest.java @@ -34,7 +34,7 @@ void coupon() { // Then assertThat(actual.getName()).isEqualTo("couponName"); - assertThat(actual.getDescription()).isEqualTo(null); + assertThat(actual.getDescription()).isNull(); assertThat(actual.getPoint()).isEqualTo(10); assertThat(actual.getStock()).isEqualTo(100); assertThat(actual.getType()).isEqualTo(CouponType.MORNING_COUPON); From 4aa35bd528979f3ed50283dbaad78efa6361ab71 Mon Sep 17 00:00:00 2001 From: HyuckJuneHong Date: Thu, 9 Nov 2023 03:52:02 +0900 Subject: [PATCH 10/10] =?UTF-8?q?fix:=20CheckStyle=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/moabam/api/domain/entity/Coupon.java | 2 +- src/main/resources/static/docs/coupon.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/moabam/api/domain/entity/Coupon.java b/src/main/java/com/moabam/api/domain/entity/Coupon.java index 4aaeb163..102da46f 100644 --- a/src/main/java/com/moabam/api/domain/entity/Coupon.java +++ b/src/main/java/com/moabam/api/domain/entity/Coupon.java @@ -41,7 +41,7 @@ public class Coupon extends BaseTimeEntity { @ColumnDefault("1") @Column(name = "point", nullable = false) private int point; - + @Column(name = "description", length = 50) private String description; diff --git a/src/main/resources/static/docs/coupon.html b/src/main/resources/static/docs/coupon.html index c6daacf7..a0074984 100644 --- a/src/main/resources/static/docs/coupon.html +++ b/src/main/resources/static/docs/coupon.html @@ -533,7 +533,7 @@

쿠폰 사용 (진행 중)