-
Notifications
You must be signed in to change notification settings - Fork 153
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
step3 (매장 식사 주문) #246
base: yuhwanwoo
Are you sure you want to change the base?
step3 (매장 식사 주문) #246
Changes from all commits
aa31b61
ce277ce
267e943
a888d59
f4da63b
33e3f30
b21163d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
package kitchenpos.deliveryorders.application; | ||
|
||
import kitchenpos.deliveryorders.domain.DeliveryOrder; | ||
import kitchenpos.deliveryorders.domain.DeliveryOrderAddress; | ||
import kitchenpos.deliveryorders.domain.DeliveryOrderLineItem; | ||
import kitchenpos.deliveryorders.domain.DeliveryOrderLineItemPrice; | ||
import kitchenpos.deliveryorders.domain.DeliveryOrderLineItemQuantity; | ||
import kitchenpos.deliveryorders.domain.DeliveryOrderLineItems; | ||
import kitchenpos.deliveryorders.domain.DeliveryOrderRepository; | ||
import kitchenpos.deliveryorders.domain.KitchenridersClient; | ||
import kitchenpos.deliveryorders.domain.MenuClient; | ||
import kitchenpos.deliveryorders.shared.dto.DeliveryOrderLineItemDto; | ||
import kitchenpos.deliveryorders.shared.dto.DeliveryOrderDto; | ||
import kitchenpos.deliveryorders.shared.dto.request.DeliveryOrderCreateRequest; | ||
import kitchenpos.shared.util.ConvertUtil; | ||
import org.springframework.stereotype.Service; | ||
import org.springframework.transaction.annotation.Transactional; | ||
|
||
import java.util.List; | ||
import java.util.NoSuchElementException; | ||
import java.util.Objects; | ||
import java.util.UUID; | ||
import java.util.stream.Collectors; | ||
|
||
@Service | ||
public class DeliveryOrderService { | ||
private DeliveryOrderRepository deliveryOrderRepository; | ||
private MenuClient menuClient; | ||
private KitchenridersClient kitchenridersClient; | ||
|
||
public DeliveryOrderService(DeliveryOrderRepository deliveryOrderRepository, MenuClient menuClient, KitchenridersClient kitchenridersClient) { | ||
this.deliveryOrderRepository = deliveryOrderRepository; | ||
this.menuClient = menuClient; | ||
this.kitchenridersClient = kitchenridersClient; | ||
} | ||
|
||
@Transactional | ||
public DeliveryOrderDto create(final DeliveryOrderCreateRequest request) { | ||
final List<DeliveryOrderLineItemDto> orderLineItemRequests = request.getOrderLineItems(); | ||
|
||
if (Objects.isNull(orderLineItemRequests) || orderLineItemRequests.isEmpty()) { | ||
throw new IllegalArgumentException(); | ||
} | ||
|
||
List<DeliveryOrderLineItem> deliveryOrderLineItems = request.getOrderLineItems().stream() | ||
.map(deliveryOrderLineItemDto -> DeliveryOrderLineItem.of( | ||
deliveryOrderLineItemDto.getMenuId(), | ||
new DeliveryOrderLineItemQuantity(deliveryOrderLineItemDto.getQuantity()), | ||
new DeliveryOrderLineItemPrice(deliveryOrderLineItemDto.getPrice()), | ||
menuClient | ||
)) | ||
.collect(Collectors.toList()); | ||
|
||
DeliveryOrder deliveryOrder = DeliveryOrder.of( | ||
new DeliveryOrderLineItems(deliveryOrderLineItems), | ||
new DeliveryOrderAddress(request.getDeliveryAddress()), | ||
menuClient | ||
); | ||
|
||
return ConvertUtil.convert(deliveryOrderRepository.save(deliveryOrder), DeliveryOrderDto.class); | ||
} | ||
|
||
@Transactional | ||
public DeliveryOrderDto accept(final UUID orderId) { | ||
DeliveryOrder deliveryOrder = deliveryOrderRepository.findById(orderId) | ||
.orElseThrow(NoSuchElementException::new); | ||
deliveryOrder.accept(kitchenridersClient); | ||
return ConvertUtil.convert(deliveryOrder, DeliveryOrderDto.class); | ||
} | ||
|
||
@Transactional | ||
public DeliveryOrderDto serve(final UUID orderId) { | ||
DeliveryOrder deliveryOrder = deliveryOrderRepository.findById(orderId) | ||
.orElseThrow(NoSuchElementException::new); | ||
deliveryOrder.serve(); | ||
return ConvertUtil.convert(deliveryOrder, DeliveryOrderDto.class); | ||
} | ||
|
||
@Transactional | ||
public DeliveryOrderDto startDelivery(final UUID orderId) { | ||
DeliveryOrder deliveryOrder = deliveryOrderRepository.findById(orderId) | ||
.orElseThrow(NoSuchElementException::new); | ||
deliveryOrder.startDelivery(); | ||
return ConvertUtil.convert(deliveryOrder, DeliveryOrderDto.class); | ||
} | ||
|
||
@Transactional | ||
public DeliveryOrderDto completeDelivery(final UUID orderId) { | ||
DeliveryOrder deliveryOrder = deliveryOrderRepository.findById(orderId) | ||
.orElseThrow(NoSuchElementException::new); | ||
deliveryOrder.completeDelivery(); | ||
return ConvertUtil.convert(deliveryOrder, DeliveryOrderDto.class); | ||
} | ||
|
||
@Transactional | ||
public DeliveryOrderDto complete(final UUID orderId) { | ||
DeliveryOrder deliveryOrder = deliveryOrderRepository.findById(orderId) | ||
.orElseThrow(NoSuchElementException::new); | ||
deliveryOrder.complete(); | ||
return ConvertUtil.convert(deliveryOrder, DeliveryOrderDto.class); | ||
} | ||
|
||
@Transactional(readOnly = true) | ||
public List<DeliveryOrderDto> findAll() { | ||
return ConvertUtil.convertList(deliveryOrderRepository.findAll(), DeliveryOrderDto.class); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
package kitchenpos.deliveryorders.domain; | ||
|
||
import kitchenpos.eatinorders.domain.OrderStatus; | ||
|
||
import javax.persistence.Column; | ||
import javax.persistence.Embedded; | ||
import javax.persistence.Entity; | ||
import javax.persistence.EnumType; | ||
import javax.persistence.Enumerated; | ||
import javax.persistence.Id; | ||
import javax.persistence.Table; | ||
import java.time.LocalDateTime; | ||
import java.util.List; | ||
import java.util.UUID; | ||
import java.util.stream.Collectors; | ||
|
||
@Table(name = "delivery_orders") | ||
@Entity | ||
public class DeliveryOrder { | ||
@Column(name = "id", columnDefinition = "binary(16)") | ||
@Id | ||
private UUID id; | ||
|
||
@Column(name = "status", nullable = false) | ||
@Enumerated(EnumType.STRING) | ||
private OrderStatus status; | ||
|
||
@Column(name = "order_date_time", nullable = false) | ||
private LocalDateTime orderDateTime; | ||
|
||
@Embedded | ||
private DeliveryOrderLineItems orderLineItems; | ||
|
||
@Embedded | ||
private DeliveryOrderAddress deliveryAddress; | ||
|
||
protected DeliveryOrder() { | ||
} | ||
|
||
public DeliveryOrder(UUID id, OrderStatus status, LocalDateTime orderDateTime, DeliveryOrderLineItems orderLineItems, DeliveryOrderAddress deliveryAddress) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 정적 팩토리메서드를 사용하게 되면 외부에서 생성자를 통해 생성하지 못하도록 수정해보는 것은 어떤가요? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이 부분에 대해 고민을 했던 부분이 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 저도 많은 고민을 했었는데요~ 테스트코드를 작성하기 위해 프로덕션 코드에 손이 가는 것이 괜찮을까? 고민이 들기는 했어요.
말씀주신 방법으로 구현해도 좋아요. 다만, 프로덕션 코드에서는 배달주문을 생성할 때 Status 값이 무조건 WAITING 이라는 점때문에 찜찜하실수 있을 것 같아요 |
||
this.id = id; | ||
this.status = status; | ||
this.orderDateTime = orderDateTime; | ||
this.orderLineItems = orderLineItems; | ||
this.deliveryAddress = deliveryAddress; | ||
} | ||
|
||
public static DeliveryOrder of(DeliveryOrderLineItems orderLineItems, DeliveryOrderAddress orderAddress, MenuClient menuClient) { | ||
validateDeliveryOrder(orderLineItems, menuClient); | ||
return new DeliveryOrder(UUID.randomUUID(), OrderStatus.WAITING, LocalDateTime.now(), orderLineItems, orderAddress); | ||
} | ||
|
||
private static void validateDeliveryOrder(DeliveryOrderLineItems orderLineItems, MenuClient menuClient) { | ||
int menusSize = menuClient.countAllByIdIn( | ||
orderLineItems.getOrderLineItems().stream() | ||
.map(DeliveryOrderLineItem::getMenuId) | ||
.collect(Collectors.toList()) | ||
); | ||
if (menusSize != orderLineItems.getOrderLineItems().size()) { | ||
throw new IllegalArgumentException(); | ||
} | ||
} | ||
|
||
public UUID getId() { | ||
return id; | ||
} | ||
|
||
public OrderStatus getStatus() { | ||
return status; | ||
} | ||
|
||
public LocalDateTime getOrderDateTime() { | ||
return orderDateTime; | ||
} | ||
|
||
public List<DeliveryOrderLineItem> getOrderLineItems() { | ||
return orderLineItems.getOrderLineItems(); | ||
} | ||
|
||
public String getDeliveryAddress() { | ||
return deliveryAddress.getDeliveryOrderAddress(); | ||
} | ||
|
||
public void accept(KitchenridersClient kitchenridersClient) { | ||
if (status != OrderStatus.WAITING) { | ||
throw new IllegalStateException(); | ||
} | ||
|
||
kitchenridersClient.requestDelivery(id, orderLineItems.getTotalDeliveryOrderLineItemsPrice(), getDeliveryAddress()); | ||
status = OrderStatus.ACCEPTED; | ||
} | ||
|
||
public void serve() { | ||
if (status != OrderStatus.ACCEPTED) { | ||
throw new IllegalStateException(); | ||
} | ||
this.status = OrderStatus.SERVED; | ||
} | ||
|
||
public void startDelivery() { | ||
if (status != OrderStatus.SERVED) { | ||
throw new IllegalStateException(); | ||
} | ||
status = OrderStatus.DELIVERING; | ||
} | ||
|
||
public void completeDelivery() { | ||
if (status != OrderStatus.DELIVERING) { | ||
throw new IllegalStateException(); | ||
} | ||
status = OrderStatus.DELIVERED; | ||
} | ||
|
||
public void complete() { | ||
if (status != OrderStatus.DELIVERED) { | ||
throw new IllegalStateException(); | ||
} | ||
status = OrderStatus.COMPLETED; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
package kitchenpos.deliveryorders.domain; | ||
|
||
import javax.persistence.Column; | ||
import javax.persistence.Embeddable; | ||
import java.util.Objects; | ||
|
||
@Embeddable | ||
public class DeliveryOrderAddress { | ||
@Column(name = "address", nullable = false) | ||
private String deliveryOrderAddress; | ||
|
||
protected DeliveryOrderAddress() { | ||
} | ||
|
||
public DeliveryOrderAddress(String deliveryOrderAddress) { | ||
validateDeliveryOrderAddress(deliveryOrderAddress); | ||
this.deliveryOrderAddress = deliveryOrderAddress; | ||
} | ||
|
||
private void validateDeliveryOrderAddress(String deliveryOrderAddress) { | ||
if (Objects.isNull(deliveryOrderAddress) || deliveryOrderAddress.isEmpty()) { | ||
throw new IllegalArgumentException(); | ||
} | ||
} | ||
|
||
public String getDeliveryOrderAddress() { | ||
return deliveryOrderAddress; | ||
} | ||
|
||
@Override | ||
public boolean equals(Object o) { | ||
if (this == o) return true; | ||
if (o == null || getClass() != o.getClass()) return false; | ||
DeliveryOrderAddress that = (DeliveryOrderAddress) o; | ||
return Objects.equals(deliveryOrderAddress, that.deliveryOrderAddress); | ||
} | ||
|
||
@Override | ||
public int hashCode() { | ||
return Objects.hash(deliveryOrderAddress); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
모델링 업데이트 👍 👍
전략적 설계를 하면서 구성하신 모델링과 실제 구현한 코드간의 싱크를 맞춰주시는 것에 대해서도 꾸준히 유지보수가 필요하다고 생각해요
모델링과 구현코드간의 싱크가 맞지 않으면, 멘탈모델이 일치하지 않아 결국 DDD 도입 전과 같은 문제들이 계속 발생하게 되는 이슈가 있어요 😢