Skip to content
This repository has been archived by the owner on Dec 4, 2024. It is now read-only.

refactor: switch the order to a clean architecture #34

Merged
merged 3 commits into from
Jul 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package br.com.fiap.grupo30.fastfood.infrastructure.persistence.entities;
package br.com.fiap.grupo30.fastfood.domain;

public enum OrderStatus {
DRAFT,
Expand Down
110 changes: 110 additions & 0 deletions src/main/java/br/com/fiap/grupo30/fastfood/domain/entities/Order.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
package br.com.fiap.grupo30.fastfood.domain.entities;

import br.com.fiap.grupo30.fastfood.domain.OrderStatus;
import br.com.fiap.grupo30.fastfood.presentation.presenters.exceptions.CompositeDomainValidationException;
import java.util.Collection;
import java.util.LinkedList;
import java.util.Objects;

public class Order {

private Long id;
private OrderStatus status;
private Customer customer;
private Payment payment;
private Collection<OrderItem> items = new LinkedList<>();
private Double totalPrice = 0.0;

public Order() {
this.status = OrderStatus.DRAFT;
}

public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

public OrderStatus getStatus() {
return status;
}

public void setStatus(OrderStatus status) {
this.status = status;
}

public Customer getCustomer() {
return customer;
}

public void setCustomer(Customer customer) {
this.customer = customer;
}

public Payment getPayment() {
return payment;
}

public void setPayment(Payment payment) {
this.payment = payment;
}

public Collection<OrderItem> getItems() {
return items;
}

public void addProduct(Product product, Long quantity) {
this.items.stream()
.filter(orderItem -> orderItem.getProduct().equals(product))
.findFirst()
.ifPresentOrElse(
existingItem ->
existingItem.setQuantity(existingItem.getQuantity() + quantity),
() -> this.items.add(new OrderItem(this, product, quantity)));

this.recalculateTotalPrice();
}

public void removeProduct(Product product) {
this.items.removeIf(orderItem -> orderItem.getProduct().equals(product));
this.recalculateTotalPrice();
}

public Double getTotalPrice() {
return totalPrice;
}

public void recalculateTotalPrice() {
this.totalPrice = this.items.stream().mapToDouble(OrderItem::getTotalPrice).sum();
}

public void validate() {
var errors = new LinkedList<String>();

if (this.status == OrderStatus.SUBMITTED && !this.hasProducts()) {
errors.add("Cannot submit order without products");
}

if (!errors.isEmpty()) {
throw new CompositeDomainValidationException(errors);
}
}

private boolean hasProducts() {
return !this.items.isEmpty();
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Order order)) return false;
return Objects.equals(id, order.id);
}

@Override
public int hashCode() {
return Objects.hash(id);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package br.com.fiap.grupo30.fastfood.domain.entities;

public class OrderItem {

private Long id;

private Order order;
private Product product;
private Long quantity;
private Double totalPrice;

public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

public OrderItem(Order order, Product product, Long quantity) {
this.order = order;
this.product = product;
this.quantity = quantity;
this.recalculateTotalPrice();
}

public Order getOrder() {
return order;
}

public void setOrder(Order order) {
this.order = order;
}

public Product getProduct() {
return product;
}

public void setProduct(Product product) {
this.product = product;
}

public Long getQuantity() {
return quantity;
}

public void setQuantity(Long quantity) {
this.quantity = quantity;
this.recalculateTotalPrice();
}

public Double getTotalPrice() {
return totalPrice;
}

private void recalculateTotalPrice() {
this.totalPrice = this.product.getPrice() * this.quantity;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package br.com.fiap.grupo30.fastfood.domain.entities;

import br.com.fiap.grupo30.fastfood.infrastructure.persistence.entities.PaymentStatus;
import java.util.Objects;

public class Payment {
private Long id;
private PaymentStatus status;
private Double amount;

public Long getId() {
return id;
}

public PaymentStatus getStatus() {
return status;
}

public Double getAmount() {
return amount;
}

public void setId(Long newId) {
this.id = newId;
}

public void setStatus(PaymentStatus newStatus) {
this.status = newStatus;
}

public void setAmount(Double newAmount) {
this.amount = newAmount;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Payment payment)) return false;
return Objects.equals(id, payment.id);
}

@Override
public int hashCode() {
return Objects.hash(id);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package br.com.fiap.grupo30.fastfood.domain.repositories;

import br.com.fiap.grupo30.fastfood.domain.OrderStatus;
import br.com.fiap.grupo30.fastfood.domain.entities.Order;
import br.com.fiap.grupo30.fastfood.domain.entities.Product;
import java.util.List;

public interface OrderRepository {

List<Order> findOrdersByStatus(OrderStatus status);

Order findById(Long orderId);

Order startNewOrder(Order order);

Order addProductToOrder(Order order, Product product, Long productQuantity);

Order removeProductFromOrder(Order order, Product product);

Order submitOrder(Order order);

Order startPreparingOrder(Order order);

Order finishPreparingOrder(Order order);

Order deliverOrder(Order order);
}
Original file line number Diff line number Diff line change
@@ -1,42 +1,30 @@
package br.com.fiap.grupo30.fastfood.domain.usecases.order;

import br.com.fiap.grupo30.fastfood.infrastructure.persistence.entities.OrderEntity;
import br.com.fiap.grupo30.fastfood.infrastructure.persistence.entities.ProductEntity;
import br.com.fiap.grupo30.fastfood.infrastructure.persistence.repositories.JpaOrderRepository;
import br.com.fiap.grupo30.fastfood.infrastructure.persistence.repositories.JpaProductRepository;
import br.com.fiap.grupo30.fastfood.presentation.presenters.dto.OrderDTO;
import br.com.fiap.grupo30.fastfood.presentation.presenters.exceptions.ResourceNotFoundException;
import jakarta.transaction.Transactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import br.com.fiap.grupo30.fastfood.domain.OrderStatus;
import br.com.fiap.grupo30.fastfood.domain.entities.Order;
import br.com.fiap.grupo30.fastfood.domain.entities.Product;
import br.com.fiap.grupo30.fastfood.infrastructure.gateways.OrderGateway;
import br.com.fiap.grupo30.fastfood.infrastructure.gateways.ProductGateway;
import br.com.fiap.grupo30.fastfood.presentation.presenters.exceptions.CantChangeOrderProductsAfterSubmitException;

@Component
public class AddProductToOrderUseCase {

private final JpaOrderRepository jpaOrderRepository;
private final JpaProductRepository jpaProductRepository;
private final OrderGateway orderGateway;
private final ProductGateway productGateway;

@Autowired
public AddProductToOrderUseCase(
JpaOrderRepository jpaOrderRepository, JpaProductRepository jpaProductRepository) {
this.jpaOrderRepository = jpaOrderRepository;
this.jpaProductRepository = jpaProductRepository;
public AddProductToOrderUseCase(OrderGateway orderGateway, ProductGateway productGateway) {
this.orderGateway = orderGateway;
this.productGateway = productGateway;
}

@Transactional
public OrderDTO execute(Long orderId, Long productId, Long productQuantity) {
OrderEntity order =
this.jpaOrderRepository
.findById(orderId)
.orElseThrow(() -> new ResourceNotFoundException("Order not found"));
public Order execute(Long orderId, Long productId, Long productQuantity) {
Order order = orderGateway.findById(orderId);

ProductEntity product =
this.jpaProductRepository
.findById(productId)
.orElseThrow(() -> new ResourceNotFoundException("Product not found"));
if (order.getStatus() != OrderStatus.DRAFT) {
throw new CantChangeOrderProductsAfterSubmitException();
}

order.addProduct(product, productQuantity);

return this.jpaOrderRepository.save(order).toDTO();
Product product = productGateway.findById(productId);
return orderGateway.addProductToOrder(order, product, productQuantity);
}
}
Original file line number Diff line number Diff line change
@@ -1,35 +1,26 @@
package br.com.fiap.grupo30.fastfood.domain.usecases.order;

import br.com.fiap.grupo30.fastfood.infrastructure.persistence.entities.OrderEntity;
import br.com.fiap.grupo30.fastfood.infrastructure.persistence.entities.OrderStatus;
import br.com.fiap.grupo30.fastfood.infrastructure.persistence.repositories.JpaOrderRepository;
import br.com.fiap.grupo30.fastfood.presentation.presenters.dto.OrderDTO;
import br.com.fiap.grupo30.fastfood.domain.OrderStatus;
import br.com.fiap.grupo30.fastfood.domain.entities.Order;
import br.com.fiap.grupo30.fastfood.infrastructure.gateways.OrderGateway;
import br.com.fiap.grupo30.fastfood.presentation.presenters.exceptions.CantChangeOrderStatusDeliveredOtherThanReadyException;
import br.com.fiap.grupo30.fastfood.presentation.presenters.exceptions.ResourceNotFoundException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class DeliverOrderUseCase {

private final JpaOrderRepository jpaOrderRepository;
private final OrderGateway orderGateway;

@Autowired
public DeliverOrderUseCase(JpaOrderRepository jpaOrderRepository) {
this.jpaOrderRepository = jpaOrderRepository;
public DeliverOrderUseCase(OrderGateway orderGateway) {
this.orderGateway = orderGateway;
}

public OrderDTO execute(Long orderId) {
OrderEntity order =
this.jpaOrderRepository
.findById(orderId)
.orElseThrow(() -> new ResourceNotFoundException("Order not found"));
public Order execute(Long orderId) {
Order order = orderGateway.findById(orderId);

if (order.getStatus() != OrderStatus.READY) {
throw new CantChangeOrderStatusDeliveredOtherThanReadyException();
}

order.setStatus(OrderStatus.DELIVERED);
return this.jpaOrderRepository.save(order).toDTO();
return orderGateway.deliverOrder(order);
}
}
Loading
Loading