diff --git a/src/main/java/me/jjeda/mall/accounts/dto/AccountDto.java b/src/main/java/me/jjeda/mall/accounts/dto/AccountDto.java index 3fb7e7f..3fb67af 100644 --- a/src/main/java/me/jjeda/mall/accounts/dto/AccountDto.java +++ b/src/main/java/me/jjeda/mall/accounts/dto/AccountDto.java @@ -15,10 +15,8 @@ import java.util.Set; //@JsonIgnoreProperties({"email", "password", "phone", "address", "accountRole"}) -@AllArgsConstructor @Getter @Builder -@NoArgsConstructor(access = AccessLevel.PROTECTED) public class AccountDto { private Long id; diff --git a/src/main/java/me/jjeda/mall/orders/controller/PaymentController.java b/src/main/java/me/jjeda/mall/orders/controller/PaymentController.java new file mode 100644 index 0000000..5195882 --- /dev/null +++ b/src/main/java/me/jjeda/mall/orders/controller/PaymentController.java @@ -0,0 +1,28 @@ +package me.jjeda.mall.orders.controller; + +import lombok.RequiredArgsConstructor; +import me.jjeda.mall.orders.domain.PaymentFactory; +import me.jjeda.mall.orders.dto.PaymentDto; +import me.jjeda.mall.orders.service.OrderService; +import me.jjeda.mall.orders.service.PaymentService; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; + +@Controller +@RequestMapping("/api/orders/payment") +@RequiredArgsConstructor +public class PaymentController { + + private final PaymentFactory paymentFactory; + private final OrderService orderService; + + @PostMapping(value = "/{orderId}") + public ResponseEntity completePayment(@RequestBody PaymentDto paymentDto, @PathVariable Long orderId) { + final PaymentService paymentService = paymentFactory.getType(paymentDto.getPaymentType()); + return ResponseEntity.ok(orderService.completePayment(paymentService, paymentDto, orderId)); + } +} diff --git a/src/main/java/me/jjeda/mall/orders/domain/CashPayment.java b/src/main/java/me/jjeda/mall/orders/domain/CashPayment.java new file mode 100644 index 0000000..017a58c --- /dev/null +++ b/src/main/java/me/jjeda/mall/orders/domain/CashPayment.java @@ -0,0 +1,40 @@ +package me.jjeda.mall.orders.domain; + +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.OneToOne; + +@Getter +@Setter +@Entity +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor(access = AccessLevel.PROTECTED) +public class CashPayment { + + @Id + @GeneratedValue + @Column(name = "cash_payment_id") + private Long id; + + private String bank; + + private String bankAccount; + + private String name; + + @OneToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "payment_id") + private Payment payment; +} diff --git a/src/main/java/me/jjeda/mall/orders/domain/CreditPayment.java b/src/main/java/me/jjeda/mall/orders/domain/CreditPayment.java new file mode 100644 index 0000000..f47068b --- /dev/null +++ b/src/main/java/me/jjeda/mall/orders/domain/CreditPayment.java @@ -0,0 +1,41 @@ +package me.jjeda.mall.orders.domain; + +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.OneToOne; + +@Getter +@Setter +@Entity +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor(access = AccessLevel.PROTECTED) +public class CreditPayment { + + @Id + @GeneratedValue + @Column(name = "credit_payment_id") + private Long id; + + private String bank; + + private String cardNumber; + + private String name; + + @OneToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "payment_id") + private Payment payment; + +} diff --git a/src/main/java/me/jjeda/mall/orders/domain/MobilePayment.java b/src/main/java/me/jjeda/mall/orders/domain/MobilePayment.java new file mode 100644 index 0000000..197bc11 --- /dev/null +++ b/src/main/java/me/jjeda/mall/orders/domain/MobilePayment.java @@ -0,0 +1,41 @@ +package me.jjeda.mall.orders.domain; + + +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.OneToOne; + +@Getter +@Setter +@Entity +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor(access = AccessLevel.PROTECTED) +public class MobilePayment { + + @Id + @GeneratedValue + @Column(name = "mobile_payment_id") + private Long id; + + private String phone; + + private String telco; + + private String name; + + @OneToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "payment_id") + private Payment payment; +} diff --git a/src/main/java/me/jjeda/mall/orders/domain/Order.java b/src/main/java/me/jjeda/mall/orders/domain/Order.java index 53d8c7a..d0f4972 100644 --- a/src/main/java/me/jjeda/mall/orders/domain/Order.java +++ b/src/main/java/me/jjeda/mall/orders/domain/Order.java @@ -1,6 +1,5 @@ package me.jjeda.mall.orders.domain; -import com.fasterxml.jackson.annotation.JsonManagedReference; import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.Builder; @@ -54,6 +53,12 @@ public class Order { @OneToMany(mappedBy = "order", cascade = CascadeType.ALL) private List orderItems; + private int totalPrice; + + @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL) + @JoinColumn(name = "payment_id") + private Payment payment; + private LocalDateTime orderAt; @Enumerated(EnumType.STRING) diff --git a/src/main/java/me/jjeda/mall/orders/domain/Payment.java b/src/main/java/me/jjeda/mall/orders/domain/Payment.java new file mode 100644 index 0000000..474365b --- /dev/null +++ b/src/main/java/me/jjeda/mall/orders/domain/Payment.java @@ -0,0 +1,50 @@ +package me.jjeda.mall.orders.domain; + +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import java.time.LocalDateTime; + +@Entity +@Getter +@Setter +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor(access = AccessLevel.PROTECTED) +public class Payment { + + @Id + @GeneratedValue + @Column(name = "payment_id") + private Long id; + + private int price; + + @Enumerated(EnumType.STRING) + private PaymentStatus paymentStatus; + + @Enumerated(EnumType.STRING) + private PaymentType paymentType; + + private LocalDateTime createdAt; + + /** + * 주문이 완료되면 결제대기상태의 결제 Entity 를 만들기 위한 메서드 + */ + public static Payment toReadyEntity() { + return Payment.builder() + .paymentStatus(PaymentStatus.READY) + .build(); + } + +} diff --git a/src/main/java/me/jjeda/mall/orders/domain/PaymentAdapter.java b/src/main/java/me/jjeda/mall/orders/domain/PaymentAdapter.java new file mode 100644 index 0000000..b7be6cf --- /dev/null +++ b/src/main/java/me/jjeda/mall/orders/domain/PaymentAdapter.java @@ -0,0 +1,85 @@ +package me.jjeda.mall.orders.domain; + +import me.jjeda.mall.orders.dto.CashPaymentDto; +import me.jjeda.mall.orders.dto.CreditPaymentDto; +import me.jjeda.mall.orders.dto.MobilePaymentDto; +import me.jjeda.mall.orders.dto.PaymentDto; + +public class PaymentAdapter { + public static Payment toEntity(PaymentDto paymentDto) { + return Payment.builder() + .id(paymentDto.getId()) + .price(paymentDto.getPrice()) + .createdAt(paymentDto.getCreatedAt()) + .paymentType(paymentDto.getPaymentType()) + .paymentStatus(paymentDto.getPaymentStatus()) + .build(); + } + + public static CashPayment toEntity(CashPaymentDto cashPaymentDto) { + return CashPayment.builder() + .id(cashPaymentDto.getCashPaymentId()) + .bank(cashPaymentDto.getBank()) + .bankAccount(cashPaymentDto.getBankAccount()) + .name(cashPaymentDto.getName()) + .payment(toEntity(cashPaymentDto.getSuperTypePaymentDto())) + .build(); + } + + public static CreditPayment toEntity(CreditPaymentDto creditPaymentDto) { + return CreditPayment.builder() + .id(creditPaymentDto.getCreditPaymentId()) + .bank(creditPaymentDto.getBank()) + .cardNumber(creditPaymentDto.getCardNumber()) + .name(creditPaymentDto.getName()) + .payment(toEntity(creditPaymentDto.getSuperTypePaymentDto())) + .build(); + } + + public static MobilePayment toEntity(MobilePaymentDto mobilePaymentDto) { + return MobilePayment.builder() + .id(mobilePaymentDto.getMobilePaymentId()) + .phone(mobilePaymentDto.getPhone()) + .telco(mobilePaymentDto.getTelco()) + .name(mobilePaymentDto.getName()) + .payment(toEntity(mobilePaymentDto.getSuperTypePaymentDto())) + .build(); + } + + public static PaymentDto toDto(Payment payment) { + return PaymentDto.builder() + .id(payment.getId()) + .price(payment.getPrice()) + .paymentStatus(payment.getPaymentStatus()) + .paymentType(payment.getPaymentType()) + .createdAt(payment.getCreatedAt()) + .build(); + } + + public static PaymentDto toDto(CashPayment cashPayment) { + return CashPaymentDto.builder() + .cashPaymentId(cashPayment.getId()) + .bank(cashPayment.getBank()) + .bankAccount(cashPayment.getBankAccount()) + .name(cashPayment.getName()) + .build(); + } + + public static PaymentDto toDto(CreditPayment creditPayment) { + return CreditPaymentDto.builder() + .creditPaymentId(creditPayment.getId()) + .bank(creditPayment.getBank()) + .cardNumber(creditPayment.getCardNumber()) + .name(creditPayment.getName()) + .build(); + } + + public static PaymentDto toDto(MobilePayment mobilePayment) { + return MobilePaymentDto.builder() + .mobilePaymentId(mobilePayment.getId()) + .phone(mobilePayment.getPhone()) + .telco(mobilePayment.getTelco()) + .name(mobilePayment.getName()) + .build(); + } +} diff --git a/src/main/java/me/jjeda/mall/orders/domain/PaymentFactory.java b/src/main/java/me/jjeda/mall/orders/domain/PaymentFactory.java new file mode 100644 index 0000000..87afb39 --- /dev/null +++ b/src/main/java/me/jjeda/mall/orders/domain/PaymentFactory.java @@ -0,0 +1,32 @@ +package me.jjeda.mall.orders.domain; + +import me.jjeda.mall.orders.service.CashPaymentService; +import me.jjeda.mall.orders.service.CreditPaymentService; +import me.jjeda.mall.orders.service.MobilePaymentService; +import me.jjeda.mall.orders.service.PaymentService; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.Map; + +@Component +public class PaymentFactory { + + private final Map map; + + public PaymentFactory(CashPaymentService cashPaymentService, CreditPaymentService creditPaymentService, + MobilePaymentService mobilePaymentService) { + map = new HashMap<>(); + map.put(PaymentType.CASH, cashPaymentService); + map.put(PaymentType.CREDIT, creditPaymentService); + map.put(PaymentType.MOBILE, mobilePaymentService); + } + + public PaymentService getType(PaymentType paymentType) { + if(map.containsKey(paymentType)) { + return map.get(paymentType); + } else { + throw new IllegalArgumentException(); + } + } +} diff --git a/src/main/java/me/jjeda/mall/orders/domain/PaymentStatus.java b/src/main/java/me/jjeda/mall/orders/domain/PaymentStatus.java new file mode 100644 index 0000000..18e1497 --- /dev/null +++ b/src/main/java/me/jjeda/mall/orders/domain/PaymentStatus.java @@ -0,0 +1,12 @@ +package me.jjeda.mall.orders.domain; + +/** + * 결제상태를 나타내는 enum + * READY : 결제전 + * COMP :결제완료 + * CANCEL : 결제취소 + * REFUND : 환불 + */ +public enum PaymentStatus { + READY, COMP, CANCEL, REFUND +} diff --git a/src/main/java/me/jjeda/mall/orders/domain/PaymentType.java b/src/main/java/me/jjeda/mall/orders/domain/PaymentType.java new file mode 100644 index 0000000..1a60271 --- /dev/null +++ b/src/main/java/me/jjeda/mall/orders/domain/PaymentType.java @@ -0,0 +1,11 @@ +package me.jjeda.mall.orders.domain; + +/** + * 결제 수단 + * CREDIT : (신용)카드 + * CASH : 계좌이체 + * MOBILE : 모바일 + */ +public enum PaymentType { + CREDIT, CASH, MOBILE +} diff --git a/src/main/java/me/jjeda/mall/orders/dto/CashPaymentDto.java b/src/main/java/me/jjeda/mall/orders/dto/CashPaymentDto.java new file mode 100644 index 0000000..1f08de3 --- /dev/null +++ b/src/main/java/me/jjeda/mall/orders/dto/CashPaymentDto.java @@ -0,0 +1,17 @@ +package me.jjeda.mall.orders.dto; + +import lombok.Getter; +import lombok.experimental.SuperBuilder; + +@Getter +@SuperBuilder +public class CashPaymentDto extends PaymentDto { + + private Long cashPaymentId; + + private String bank; + + private String bankAccount; + + private String name; +} diff --git a/src/main/java/me/jjeda/mall/orders/dto/CreditPaymentDto.java b/src/main/java/me/jjeda/mall/orders/dto/CreditPaymentDto.java new file mode 100644 index 0000000..69827a4 --- /dev/null +++ b/src/main/java/me/jjeda/mall/orders/dto/CreditPaymentDto.java @@ -0,0 +1,17 @@ +package me.jjeda.mall.orders.dto; + +import lombok.Getter; +import lombok.experimental.SuperBuilder; + +@Getter +@SuperBuilder +public class CreditPaymentDto extends PaymentDto { + + private Long creditPaymentId; + + private String bank; + + private String cardNumber; + + private String name; +} diff --git a/src/main/java/me/jjeda/mall/orders/dto/MobilePaymentDto.java b/src/main/java/me/jjeda/mall/orders/dto/MobilePaymentDto.java new file mode 100644 index 0000000..8436b91 --- /dev/null +++ b/src/main/java/me/jjeda/mall/orders/dto/MobilePaymentDto.java @@ -0,0 +1,17 @@ +package me.jjeda.mall.orders.dto; + +import lombok.Getter; +import lombok.experimental.SuperBuilder; + +@Getter +@SuperBuilder +public class MobilePaymentDto extends PaymentDto { + + private Long mobilePaymentId; + + private String phone; + + private String telco; + + private String name; +} diff --git a/src/main/java/me/jjeda/mall/orders/dto/OrderDto.java b/src/main/java/me/jjeda/mall/orders/dto/OrderDto.java index 7fcd4d2..737426b 100644 --- a/src/main/java/me/jjeda/mall/orders/dto/OrderDto.java +++ b/src/main/java/me/jjeda/mall/orders/dto/OrderDto.java @@ -9,6 +9,7 @@ import me.jjeda.mall.orders.domain.Order; import me.jjeda.mall.orders.domain.OrderItem; import me.jjeda.mall.orders.domain.OrderStatus; +import me.jjeda.mall.orders.domain.Payment; import java.time.LocalDateTime; import java.util.ArrayList; @@ -27,11 +28,12 @@ public class OrderDto { public Order toEntity() { List tempOrderItems = new ArrayList<>(); - orderItemDtoList.forEach((dto)->tempOrderItems.add(dto.toEntity())); + orderItemDtoList.forEach((dto) -> tempOrderItems.add(dto.toEntity())); return Order.builder() .delivery(this.deliveryDto.toEntity()) .orderItems(tempOrderItems) + .payment(Payment.toReadyEntity()) .status(OrderStatus.ORDER) .orderAt(LocalDateTime.now()) .build(); diff --git a/src/main/java/me/jjeda/mall/orders/dto/PaymentDto.java b/src/main/java/me/jjeda/mall/orders/dto/PaymentDto.java new file mode 100644 index 0000000..dab8ab8 --- /dev/null +++ b/src/main/java/me/jjeda/mall/orders/dto/PaymentDto.java @@ -0,0 +1,29 @@ +package me.jjeda.mall.orders.dto; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; +import lombok.experimental.SuperBuilder; +import me.jjeda.mall.orders.domain.PaymentStatus; +import me.jjeda.mall.orders.domain.PaymentType; + +import java.time.LocalDateTime; + +@SuperBuilder +@Getter +@Setter +@AllArgsConstructor +public class PaymentDto { + + private Long id; + + private int price; + + private PaymentStatus paymentStatus; + + private PaymentType paymentType; + + private LocalDateTime createdAt; + + private PaymentDto superTypePaymentDto; +} diff --git a/src/main/java/me/jjeda/mall/orders/repository/CashPaymentRepository.java b/src/main/java/me/jjeda/mall/orders/repository/CashPaymentRepository.java new file mode 100644 index 0000000..70cd399 --- /dev/null +++ b/src/main/java/me/jjeda/mall/orders/repository/CashPaymentRepository.java @@ -0,0 +1,7 @@ +package me.jjeda.mall.orders.repository; + +import me.jjeda.mall.orders.domain.CashPayment; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface CashPaymentRepository extends JpaRepository { +} diff --git a/src/main/java/me/jjeda/mall/orders/repository/CreditPaymentRepository.java b/src/main/java/me/jjeda/mall/orders/repository/CreditPaymentRepository.java new file mode 100644 index 0000000..fb7e6b6 --- /dev/null +++ b/src/main/java/me/jjeda/mall/orders/repository/CreditPaymentRepository.java @@ -0,0 +1,8 @@ +package me.jjeda.mall.orders.repository; + +import me.jjeda.mall.orders.domain.CreditPayment; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface CreditPaymentRepository extends JpaRepository { + +} diff --git a/src/main/java/me/jjeda/mall/orders/repository/MobilePaymentRepository.java b/src/main/java/me/jjeda/mall/orders/repository/MobilePaymentRepository.java new file mode 100644 index 0000000..b450ff5 --- /dev/null +++ b/src/main/java/me/jjeda/mall/orders/repository/MobilePaymentRepository.java @@ -0,0 +1,7 @@ +package me.jjeda.mall.orders.repository; + +import me.jjeda.mall.orders.domain.MobilePayment; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface MobilePaymentRepository extends JpaRepository { +} diff --git a/src/main/java/me/jjeda/mall/orders/repository/PaymentRepository.java b/src/main/java/me/jjeda/mall/orders/repository/PaymentRepository.java new file mode 100644 index 0000000..af3c5c9 --- /dev/null +++ b/src/main/java/me/jjeda/mall/orders/repository/PaymentRepository.java @@ -0,0 +1,7 @@ +package me.jjeda.mall.orders.repository; + +import me.jjeda.mall.orders.domain.Payment; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface PaymentRepository extends JpaRepository { +} diff --git a/src/main/java/me/jjeda/mall/orders/service/CashPaymentService.java b/src/main/java/me/jjeda/mall/orders/service/CashPaymentService.java new file mode 100644 index 0000000..c119e08 --- /dev/null +++ b/src/main/java/me/jjeda/mall/orders/service/CashPaymentService.java @@ -0,0 +1,27 @@ +package me.jjeda.mall.orders.service; + +import lombok.RequiredArgsConstructor; +import me.jjeda.mall.orders.domain.CashPayment; +import me.jjeda.mall.orders.domain.PaymentAdapter; +import me.jjeda.mall.orders.dto.CashPaymentDto; +import me.jjeda.mall.orders.dto.PaymentDto; +import me.jjeda.mall.orders.repository.CashPaymentRepository; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@RequiredArgsConstructor +@Service +public class CashPaymentService implements PaymentService { + + private final CashPaymentRepository cashPaymentRepository; + + @Override + @Transactional + public PaymentDto savePaymentInfo(PaymentDto paymentDto) { + CashPaymentDto cashPaymentDto = (CashPaymentDto) paymentDto; + CashPayment cashPayment = PaymentAdapter.toEntity(cashPaymentDto); + cashPaymentRepository.save(cashPayment); + + return PaymentAdapter.toDto(cashPayment); + } +} diff --git a/src/main/java/me/jjeda/mall/orders/service/CreditPaymentService.java b/src/main/java/me/jjeda/mall/orders/service/CreditPaymentService.java new file mode 100644 index 0000000..1f39e2b --- /dev/null +++ b/src/main/java/me/jjeda/mall/orders/service/CreditPaymentService.java @@ -0,0 +1,28 @@ +package me.jjeda.mall.orders.service; + +import lombok.RequiredArgsConstructor; +import me.jjeda.mall.orders.domain.CreditPayment; +import me.jjeda.mall.orders.domain.PaymentAdapter; +import me.jjeda.mall.orders.dto.CreditPaymentDto; +import me.jjeda.mall.orders.dto.PaymentDto; +import me.jjeda.mall.orders.repository.CreditPaymentRepository; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@RequiredArgsConstructor +@Service +public class CreditPaymentService implements PaymentService { + + private final CreditPaymentRepository creditPaymentRepository; + + @Override + @Transactional + public PaymentDto savePaymentInfo(PaymentDto paymentDto) { + CreditPaymentDto creditPaymentDto = (CreditPaymentDto) paymentDto; + CreditPayment creditPayment = PaymentAdapter.toEntity(creditPaymentDto); + creditPaymentRepository.save(creditPayment); + + return PaymentAdapter.toDto(creditPayment); + } + +} diff --git a/src/main/java/me/jjeda/mall/orders/service/MobilePaymentService.java b/src/main/java/me/jjeda/mall/orders/service/MobilePaymentService.java new file mode 100644 index 0000000..2cb350b --- /dev/null +++ b/src/main/java/me/jjeda/mall/orders/service/MobilePaymentService.java @@ -0,0 +1,27 @@ +package me.jjeda.mall.orders.service; + +import lombok.RequiredArgsConstructor; +import me.jjeda.mall.orders.domain.MobilePayment; +import me.jjeda.mall.orders.domain.PaymentAdapter; +import me.jjeda.mall.orders.dto.MobilePaymentDto; +import me.jjeda.mall.orders.dto.PaymentDto; +import me.jjeda.mall.orders.repository.MobilePaymentRepository; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@RequiredArgsConstructor +@Service +public class MobilePaymentService implements PaymentService { + + private final MobilePaymentRepository mobilePaymentRepository; + + @Override + @Transactional + public PaymentDto savePaymentInfo(PaymentDto paymentDto) { + MobilePaymentDto mobilePaymentDto = (MobilePaymentDto) paymentDto; + MobilePayment mobilePayment = PaymentAdapter.toEntity(mobilePaymentDto); + mobilePaymentRepository.save(mobilePayment); + + return PaymentAdapter.toDto(mobilePayment); + } +} diff --git a/src/main/java/me/jjeda/mall/orders/service/OrderService.java b/src/main/java/me/jjeda/mall/orders/service/OrderService.java index 7ca90b7..78ab4ca 100644 --- a/src/main/java/me/jjeda/mall/orders/service/OrderService.java +++ b/src/main/java/me/jjeda/mall/orders/service/OrderService.java @@ -8,12 +8,17 @@ import me.jjeda.mall.orders.domain.Order; import me.jjeda.mall.orders.domain.OrderItem; import me.jjeda.mall.orders.domain.OrderStatus; +import me.jjeda.mall.orders.domain.Payment; +import me.jjeda.mall.orders.domain.PaymentAdapter; +import me.jjeda.mall.orders.domain.PaymentStatus; import me.jjeda.mall.orders.dto.OrderDto; +import me.jjeda.mall.orders.dto.PaymentDto; import me.jjeda.mall.orders.repository.OrderRepository; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.persistence.EntityNotFoundException; +import java.time.LocalDateTime; import java.util.List; import java.util.Objects; @@ -29,16 +34,17 @@ public Order createOrder(OrderDto orderDto, AccountDto accountDto) { // 연관관계 메서드 order.setAccount(AccountAndDtoAdapter.dtoToEntity(accountDto)); - //TODO : account.insertOrder(order); + //TODO : [#33] Account <-> Order 연관관계 메서드 처리 + // order.getAccount().insertOrder(order); order.getDelivery().setOrder(order); List orderItems = order.getOrderItems(); - orderItems.forEach((orderItem) -> orderItem.setOrder(order)); - /* 주문이 완료되면 아이템의 전체 재고에서 주문수량만큼 빼주어야한다. */ - //TODO : 벌크호출 + 결제가 완료되면 결제쪽에서 해주어야함 - orderItems.forEach((orderItem) -> - itemService.decrementStock(orderItem.getItem().getId(), orderItem.getQuantity()) - ); + int totalPrice = 0; + for (OrderItem item : orderItems) { + item.setOrder(order); + totalPrice += item.getOrderPrice() * item.getQuantity(); + } + order.setTotalPrice(totalPrice); return orderRepository.save(order); } @@ -47,13 +53,6 @@ public Order getOrder(Long orderId) { return orderRepository.findById(orderId).orElseThrow(EntityNotFoundException::new); } - //TODO [#25] : 주문생성 -> 결제 -> 배송 에서 결제단계 - public Order payForOrder() { - - return null; - } - - @Transactional public Order changeDeliveryStatus(Long orderId, DeliveryStatus deliveryStatus) { Order order = orderRepository.findById(orderId).orElseThrow(EntityNotFoundException::new); @@ -64,7 +63,6 @@ public Order changeDeliveryStatus(Long orderId, DeliveryStatus deliveryStatus) { return order; } - @Transactional public Order cancelOrder(Long orderId) { Order order = orderRepository.findById(orderId).orElseThrow(EntityNotFoundException::new); @@ -75,6 +73,7 @@ public Order cancelOrder(Long orderId) { } order.setStatus(OrderStatus.CANCEL); + //TODO : 주문 취소 ->결제 취소 할때로 변경 /* 주문을 취소하면 주문했던 수량만큼 다시 재고에 추가해주어야한다 */ List orderItems = order.getOrderItems(); orderItems.forEach((orderItem) -> @@ -83,4 +82,25 @@ public Order cancelOrder(Long orderId) { return order; } + + @Transactional + public PaymentDto completePayment(PaymentService paymentService, PaymentDto paymentDto, Long orderId) { + Order order = getOrder(orderId); + Payment payment = order.getPayment(); + List orderItems = order.getOrderItems(); + + payment.setPaymentStatus(PaymentStatus.COMP); + payment.setPaymentType(paymentDto.getPaymentType()); + payment.setCreatedAt(LocalDateTime.now()); + payment.setPrice(paymentDto.getPrice()); + + paymentDto.setSuperTypePaymentDto(PaymentAdapter.toDto(payment)); + + /* 주문이 완료되면 아이템의 전체 재고에서 주문수량만큼 빼주어야한다. */ + //TODO : N+1문제 -> 벌크호출 + orderItems.forEach((orderItem) -> + itemService.decrementStock(orderItem.getItem().getId(), orderItem.getQuantity()) + ); + return paymentService.savePaymentInfo(paymentDto); + } } diff --git a/src/main/java/me/jjeda/mall/orders/service/PaymentService.java b/src/main/java/me/jjeda/mall/orders/service/PaymentService.java new file mode 100644 index 0000000..0823d69 --- /dev/null +++ b/src/main/java/me/jjeda/mall/orders/service/PaymentService.java @@ -0,0 +1,9 @@ +package me.jjeda.mall.orders.service; + +import me.jjeda.mall.orders.dto.PaymentDto; +import org.springframework.stereotype.Service; + +@Service +public interface PaymentService { + PaymentDto savePaymentInfo(PaymentDto paymentDto); +} diff --git a/src/test/java/me/jjeda/mall/orders/controller/OrderControllerTest.java b/src/test/java/me/jjeda/mall/orders/controller/OrderControllerTest.java index f8e55f8..ab5755a 100644 --- a/src/test/java/me/jjeda/mall/orders/controller/OrderControllerTest.java +++ b/src/test/java/me/jjeda/mall/orders/controller/OrderControllerTest.java @@ -46,7 +46,6 @@ public class OrderControllerTest extends BaseControllerTest { @Autowired private OrderService orderService; - @TestDescription("정상적으로 주문을 완료하는 테스트") @Test @Transactional diff --git a/src/test/java/me/jjeda/mall/orders/service/OrderServiceTest.java b/src/test/java/me/jjeda/mall/orders/service/OrderServiceTest.java index 08d0822..e342242 100644 --- a/src/test/java/me/jjeda/mall/orders/service/OrderServiceTest.java +++ b/src/test/java/me/jjeda/mall/orders/service/OrderServiceTest.java @@ -1,7 +1,6 @@ package me.jjeda.mall.orders.service; import me.jjeda.mall.accounts.domain.Account; -import me.jjeda.mall.accounts.domain.AccountAndDtoAdapter; import me.jjeda.mall.accounts.domain.AccountRole; import me.jjeda.mall.accounts.dto.AccountDto; import me.jjeda.mall.common.TestDescription; @@ -13,7 +12,11 @@ import me.jjeda.mall.orders.domain.Order; import me.jjeda.mall.orders.domain.OrderItem; import me.jjeda.mall.orders.domain.OrderStatus; +import me.jjeda.mall.orders.domain.Payment; +import me.jjeda.mall.orders.domain.PaymentStatus; +import me.jjeda.mall.orders.domain.PaymentType; import me.jjeda.mall.orders.dto.OrderDto; +import me.jjeda.mall.orders.dto.PaymentDto; import me.jjeda.mall.orders.repository.OrderRepository; import org.junit.Test; import org.junit.runner.RunWith; @@ -47,6 +50,9 @@ public class OrderServiceTest { @Mock ItemService itemService; + @Mock + PaymentService paymentService; + private Account seller = Account.builder() .accountRole(Set.of(AccountRole.USER)) @@ -100,12 +106,18 @@ public class OrderServiceTest { .orderPrice(item2.getPrice() * 3) .build(); + private Payment payment = Payment.builder() + .id(1L) + .paymentStatus(PaymentStatus.READY) + .build(); + private Order order = Order.builder() .id(1L) .orderAt(LocalDateTime.now()) .status(OrderStatus.ORDER) .orderItems(List.of(orderItem1, orderItem2)) .delivery(delivery) + .payment(payment) .build(); @Test @@ -123,6 +135,7 @@ public void createOrder() { assertThat(order.getDelivery().getOrder()).isEqualTo(order); assertThat(order.getAccount().getEmail()).isEqualTo(buyerDto.getEmail()); assertThat(order.getOrderItems().get(0).getOrder()).isEqualTo(order); + assertThat(order.getPayment().getPaymentStatus()).isEqualTo(PaymentStatus.READY); } @Test @@ -196,7 +209,7 @@ public void cancelOrder_Throw_Entity_Not_Found() { } @Test(expected = IllegalStateException.class) - @TestDescription("배송준비 상태일 때 예외가 발생하는 테스트") + @TestDescription("배송준비 상태일 때 주문을 취소하면 예외가 발생하는 테스트") public void cancelOrder_Throw_Illegal_State() { //given order.getDelivery().setStatus(DeliveryStatus.DELIVERY); @@ -206,4 +219,25 @@ public void cancelOrder_Throw_Illegal_State() { orderService.cancelOrder(1L); } + @Test + @TestDescription("결제를 완료 했을 때 결제정보가 저장되는 테스트") + public void completePayment() { + + //given + PaymentDto paymentDto = PaymentDto.builder() + .price(10000) + .paymentType(PaymentType.CASH) + .build(); + given(orderRepository.findById(1L)).willReturn(Optional.of(order)); + + + //when + orderService.completePayment(paymentService, paymentDto, 1L); + + //then + assertThat(order.getPayment().getPaymentStatus()).isEqualTo(PaymentStatus.COMP); + assertThat(order.getPayment().getPrice()).isEqualTo(10000); + assertThat(order.getPayment().getPaymentType()).isEqualTo(PaymentType.CASH); + } + } \ No newline at end of file diff --git a/src/test/java/me/jjeda/mall/orders/service/PaymentServiceTest.java b/src/test/java/me/jjeda/mall/orders/service/PaymentServiceTest.java new file mode 100644 index 0000000..0847573 --- /dev/null +++ b/src/test/java/me/jjeda/mall/orders/service/PaymentServiceTest.java @@ -0,0 +1,63 @@ +package me.jjeda.mall.orders.service; + +import me.jjeda.mall.common.TestDescription; +import me.jjeda.mall.orders.domain.CashPayment; +import me.jjeda.mall.orders.domain.PaymentAdapter; +import me.jjeda.mall.orders.domain.PaymentStatus; +import me.jjeda.mall.orders.domain.PaymentType; +import me.jjeda.mall.orders.dto.CashPaymentDto; +import me.jjeda.mall.orders.dto.PaymentDto; +import me.jjeda.mall.orders.repository.CashPaymentRepository; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; + +import java.time.LocalDateTime; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +@RunWith(MockitoJUnitRunner.class) +public class PaymentServiceTest { + + @InjectMocks + private CashPaymentService cashPaymentService; + + @Mock + private CashPaymentRepository cashPaymentRepository; + + @Test + @TestDescription("정상적으로 현금결제정보 저장하는 테스트") + public void savePaymentInfo_cash() { + + //given + PaymentDto superPaymentDto = PaymentDto.builder() + .id(1L) + .paymentStatus(PaymentStatus.COMP) + .paymentType(PaymentType.CASH) + .price(10000) + .build(); + CashPaymentDto cashPaymentDto = CashPaymentDto.builder() + .cashPaymentId(2L) + .name("jjeda") + .bank("kakao") + .bankAccount("1234") + .superTypePaymentDto(superPaymentDto) + .build(); + + //when + PaymentDto returnDto = cashPaymentService.savePaymentInfo(cashPaymentDto); + CashPaymentDto returnCashPaymentDto = (CashPaymentDto)returnDto; + + assertThat(returnCashPaymentDto.getCashPaymentId()).isEqualTo(2L); + assertThat(returnCashPaymentDto.getName()).isEqualTo("jjeda"); + assertThat(returnCashPaymentDto.getBank()).isEqualTo("kakao"); + assertThat(returnCashPaymentDto.getBankAccount()).isEqualTo("1234"); + } + +}