Commit b5e22fc2 authored by 0Tyler's avatar 0Tyler

feat: checkout api

parent 1b6ac182
package edu.prlab.ecsimple.common.exception;
public class BusinessException extends RuntimeException {
public BusinessException(String message) {
super(message);
}
}
package edu.prlab.ecsimple.common.handler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.lang.NonNull;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
@Order(Ordered.HIGHEST_PRECEDENCE)
@ControllerAdvice
@Slf4j
public class RestExceptionHandler extends ResponseEntityExceptionHandler {
@ExceptionHandler(Exception.class)
protected ResponseEntity<Object> handleAll(Exception ex, WebRequest request) {
ex.printStackTrace();
return handleExceptionInternal(ex, ex.getMessage(), new HttpHeaders(), HttpStatus.INTERNAL_SERVER_ERROR, request);
}
@NonNull
@Override
protected ResponseEntity<Object> handleHttpMessageNotReadable(
@NonNull HttpMessageNotReadableException ex, @NonNull HttpHeaders headers, @NonNull HttpStatus status, @NonNull WebRequest request) {
return new ResponseEntity<>(ex.getMessage(), new HttpHeaders(), HttpStatus.BAD_REQUEST);
}
}
......@@ -2,10 +2,14 @@ package edu.prlab.ecsimple.common.mapper;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
public class MapperUtil {
private final static ObjectMapper mapper = new ObjectMapper();
public static JsonNode objectToJsonNode(Object obj) {
mapper.registerModule(new JavaTimeModule());
mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
return mapper.valueToTree(obj);
}
}
......@@ -40,16 +40,5 @@ public class DefaultDataBean implements ApplicationRunner {
.tags(List.of("tag2", "tag3"))
.quantity(20)
.build());
TheOrder order1 = orderService.create(TheOrder.builder()
.email("email")
.state("state")
.checkoutDate(LocalDateTime.now())
.build())
.orElseThrow(() -> new EntityNotFoundException("no order"));
Item item1 = orderService.create(Item.builder()
.quantity(1)
.build())
.orElseThrow(() -> new EntityNotFoundException("no Item"));
orderService.addItemToOrder(order1.getIid(), item1.getSku());
}
}
......@@ -13,12 +13,10 @@ import javax.persistence.*;
@NoArgsConstructor
@AllArgsConstructor
@Entity
public class Item {
public class LineItem {
@Id
@GenericGenerator(name = "uuid2", strategy = "uuid2")
@GeneratedValue(strategy = GenerationType.IDENTITY, generator = "uuid2")
@Column(length = 36, nullable = false, updatable = false)
@Column(length = 36, nullable = false)
private String sku;
@Column
......
......@@ -9,7 +9,6 @@ import javax.persistence.*;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
@Data
@Builder
......@@ -25,11 +24,14 @@ public class TheOrder {
@Builder.Default
@ManyToMany(fetch = FetchType.EAGER)
private Collection<Item> items = new ArrayList<>();
private Collection<LineItem> lineItems = new ArrayList<>();
@Column
private String email;
@Column
private String creditCard;
@Column(columnDefinition = "TIMESTAMP")
private LocalDateTime checkoutDate;
......
package edu.prlab.ecsimple.model;
import edu.prlab.ecsimple.domain.Item;
import edu.prlab.ecsimple.domain.LineItem;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.FetchType;
import javax.persistence.ManyToMany;
import java.util.ArrayList;
import java.util.Collection;
......@@ -17,7 +15,7 @@ import java.util.Collection;
@AllArgsConstructor
public class OrderModel {
@Builder.Default
private Collection<Item> lineItems = new ArrayList<>();
private Collection<LineItem> lineItems = new ArrayList<>();
private String email;
private String creditCard;
}
package edu.prlab.ecsimple.repo;
import edu.prlab.ecsimple.domain.Item;
import edu.prlab.ecsimple.domain.LineItem;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface ItemRepo extends JpaRepository<Item, String> {
public interface ItemRepo extends JpaRepository<LineItem, String> {
}
package edu.prlab.ecsimple.service;
import edu.prlab.ecsimple.domain.Item;
import edu.prlab.ecsimple.domain.LineItem;
import edu.prlab.ecsimple.domain.TheOrder;
import edu.prlab.ecsimple.model.OrderModel;
......@@ -8,7 +8,7 @@ import java.util.Optional;
public interface OrderService {
Optional<TheOrder> create(TheOrder theOrder);
Optional<Item> create(Item item);
Optional<LineItem> addItemFromProduct(LineItem lineItem);
void addItemToOrder(Integer orderId, String sku);
Optional<TheOrder> checkout(OrderModel orderModel);
......
package edu.prlab.ecsimple.service;
import edu.prlab.ecsimple.common.exception.BusinessException;
import edu.prlab.ecsimple.common.exception.EntityNotFoundException;
import edu.prlab.ecsimple.domain.Item;
import edu.prlab.ecsimple.domain.LineItem;
import edu.prlab.ecsimple.domain.TheOrder;
import edu.prlab.ecsimple.model.OrderModel;
import edu.prlab.ecsimple.model.ResponseModel;
import edu.prlab.ecsimple.repo.ItemRepo;
import edu.prlab.ecsimple.repo.OrderRepo;
import edu.prlab.ecsimple.repo.ProductRepo;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Collection;
import java.util.Optional;
import java.util.stream.Collectors;
......@@ -25,6 +25,8 @@ public class OrderServiceImpl implements OrderService {
private final OrderRepo orderRepo;
private final ItemRepo itemRepo;
private final ProductRepo productRepo;
@Override
public Optional<TheOrder> create(TheOrder theOrder) {
return Optional.of(theOrder)
......@@ -32,16 +34,25 @@ public class OrderServiceImpl implements OrderService {
}
@Override
public Optional<Item> create(Item item) {
return Optional.of(item)
.map(it -> itemRepo.save(item));
public Optional<LineItem> addItemFromProduct(LineItem lineItem) {
return Optional.of(lineItem)
.map(it -> productRepo.findById(it.getSku())
.map(product -> {
var leftQty = product.getQuantity() - lineItem.getQuantity();
if (leftQty < 0) {
throw new BusinessException("There is not enough stock with product: " + product.getSku());
}
product.setQuantity(leftQty);
return itemRepo.save(lineItem);
})
.orElseThrow(() -> new EntityNotFoundException("Not found Product: " + it.getSku())));
}
@Override
public void addItemToOrder(Integer orderId, String sku) {
orderRepo.findById(orderId)
.map(order -> itemRepo.findById(sku)
.map(item -> order.getItems().add(item))
.map(item -> order.getLineItems().add(item))
.orElseThrow(() -> new EntityNotFoundException("No found this order")))
.orElseThrow(() -> new EntityNotFoundException("No found this order"));
}
......@@ -52,14 +63,17 @@ public class OrderServiceImpl implements OrderService {
return Optional.of(orderModel)
.map(it -> orderRepo.save(TheOrder.builder()
.email(orderModel.getEmail())
.creditCard(orderModel.getCreditCard())
.state("created")
.checkoutDate(LocalDateTime.now())
.build()))
.map(order -> {
orderModel.getLineItems().stream()
.map(it -> create(it)
.orElseThrow(() -> new RuntimeException("save item error")))
.forEach(it -> addItemToOrder(order.getIid(), it.getSku()));
Collection<LineItem> lineItems = orderModel.getLineItems().stream()
.map(it -> addItemFromProduct(it)
.orElseThrow(() -> new RuntimeException("Save lineItem error")))
.peek(it -> addItemToOrder(order.getIid(), it.getSku()))
.collect(Collectors.toList());
order.setLineItems(lineItems);
return order;
});
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment