Θα δημιουργήσουμε το Angular checkout-page component, στο οποίο ο χρήστης θα συμπληρώνει τα στοιχεία του και θα ολοκληρώνει την παραγγελία του.
Αρχικά, θα δημιουργήσουμε τέσσερις πίνακες : billing_info, shipping_info, order και order_products
Δημιουργούμε τον πίνακα billing_info, o οποίος θα περιέχει τα στοιχεία χρέωσης της παραγγελίας.
Δημιουργούμε το entity BillingInfo στο springeshop.model
@Entity
@Table(name = "billing_info")
public class BillingInfo{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private int id;
@Column(name = "first_name")
@NotNull(message = "Please provide first name")
@Size(min = 3, max = 200, message = "First Name must be between 3 and 200 characters")
private String first_name;
@Column(name = "last_name")
@NotNull(message = "Please provide last name")
@Size(min = 3, max = 200, message = "Last Name must be between 3 and 200 characters")
private String last_name;
@Column(name = "street")
@NotNull(message = "Please provide street name")
@Size(min = 3, max = 200, message = "street must be between 3 and 200 characters")
private String street;
@Column(name = "post_code")
@NotNull(message = "Please provide post code")
private String post_code;
@Column(name = "city")
@NotNull(message = "Please provide city")
@Size(min = 3, max = 200, message = "City must be between 3 and 200 characters")
private String city;
@Column(name = "phone")
@NotNull(message = "Please provide phone")
private String phone;
@Column(name = "method")
@NotNull(message = "Please provide method")
private String method;
public BillingInfo() {}
//Getters - Setters ...
}
Δημιουργούμε τον πίνακα shipping_info, ο οποίος περιέχει τα στοιχεία αποστολής της παραγγελίας και το entity ShippingInfo στο springeshop.model
@Entity
@Table(name = "shipping_info")
public class ShippingInfo{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private int id;
@Column(name = "first_name")
@NotNull(message = "Please provide first name")
@Size(min = 3, max = 200, message = "First Name must be between 3 and 200 characters")
private String first_name;
@Column(name = "last_name")
@NotNull(message = "Please provide last name")
@Size(min = 3, max = 200, message = "Last Name must be between 3 and 200 characters")
private String last_name;
@Column(name = "street")
@NotNull(message = "Please provide street name")
@Size(min = 3, max = 200, message = "street must be between 3 and 200 characters")
private String street;
@Column(name = "post_code")
@NotNull(message = "Please provide post code")
private String post_code;
@Column(name = "city")
@NotNull(message = "Please provide city")
@Size(min = 3, max = 200, message = "City must be between 3 and 200 characters")
private String city;
@Column(name = "phone")
@NotNull(message = "Please provide phone")
private String phone;
@Column(name = "method")
@NotNull(message = "Please provide method")
private String method;
public ShippingInfo() {}
//Getters - Setters ...
}
Δημιουργούμε τον πίνακα orders, ο οποίος περιέχει τις παραγγελίες και το entity Order στο springeshop.model
@Entity
@Table(name = "orders")
public class Order{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private int id;
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id")
private User user;
@Column(name = "email")
@NotNull(message = "Please provide email")
@Email
private String email;
@Column(name = "status")
@NotNull(message = "Please provide status")
private String status;
@Column(name = "order_date")
private Timestamp order_date;
@Column(name = "payment_date")
private Timestamp payment_date;
@Column(name = "shipping_date")
private Timestamp shipping_date;
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "shipping_info_id")
private ShippingInfo shippingInfo;
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "billing_info_id")
private BillingInfo billingInfo;
public Order() {}
//Getters - Setters ...
}
Δημιουργούμε τον πίνακα order_products, ο οποίος περιέχει τα προιόντα της κάθε παραγγελίας, το σύνθετο πρωτεύον κλειδί OrderProductPrimaryKey και το entity OrderProduct στο springeshop.model
@Embeddable
public class OrderProductPrimaryKey implements Serializable{
private int orderId;
private int productId;
public OrderProductPrimaryKey() {}
//Getters - Setters ...
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof OrderProductPrimaryKey)) return false;
OrderProductPrimaryKey that = (OrderProductPrimaryKey) o;
return Objects.equals(getOrderId(), that.getOrderId()) && Objects.equals(getProductId(), that.getProductId());
}
@Override
public int hashCode() {
return Objects.hash(getOrderId(), getProductId());
}
}
@Entity
@Table(name = "order_products")
public class OrderProduct{
@EmbeddedId
private OrderProductPrimaryKey id;
@OneToOne(fetch = FetchType.LAZY)
@MapsId("orderId")
private Order order;
@OneToOne(fetch = FetchType.LAZY)
@MapsId("productId")
private Product product;
@Column(name = "quantity")
@NotNull(message = "Please provide quantity")
private int quantity;
public OrderProduct() {}
//Getters - Setters ...
}
Δημιουργούμε το OrderDetails στο springeshop.model
public class OrderDetails{
@Email
private String email;
@Valid
private ShippingInfo shipping_info ;
@Valid
private BillingInfo billing_info;
private boolean isBillingAddressSameWithShippingAddress;
private List<CartProduct> cartProducts;
public OrderDetails() {}
//Getters - Setters ...
}
Δημιουργούμε τα repositories BillingInfoRepository, ShippingInfoRepository.
package springeshop.repositories;
@Repository
public interface BillingInfoRepository extends JpaRepository<BillingInfo, Integer> {
}
package springeshop.repositories;
@Repository
public interface ShippingInfoRepository extends JpaRepository<ShippingInfo, Integer> {
}
Δημιουργούμε τα BillingInfoService, ShippingInfoService, BillingInfoServiceImpl, ShippingInfoServiceImplστο springeshop.service .
package springeshop.service;
public interface BillingInfoService{
boolean saveBillingInfoAndIsSuccess(BillingInfo billingInfo);
}
package springeshop.service;
public interface ShippingInfoService{
boolean saveShippingInfoAndIsSuccess(ShippingInfo shippingInfo);
}
package springeshop.service;
@Service("billingInfoService")
@Transactional
public class BillingInfoServiceImpl implements BillingInfoService{
@Autowired
private BillingInfoRepository billingInfoRepository;
@Override
public boolean saveBillingInfoAndIsSuccess(BillingInfo billingInfo) {
boolean isSuccess = false;
try {
billingInfoRepository.save(billingInfo);
isSuccess = true;
} catch (DataAccessException exception) {
System.out.println(exception);
isSuccess = false;
}
return isSuccess;
}
}
package springeshop.service;
@Service("shippingInfoService")
@Transactional
public class ShippingInfoServiceImpl implements ShippingInfoService{
@Autowired
private ShippingInfoRepository shippingInfoRepository;
@Override
public boolean saveShippingInfoAndIsSuccess(ShippingInfo shippingInfo) {
boolean isSuccess = false;
try {
shippingInfoRepository.save(shippingInfo);
isSuccess = true;
} catch (DataAccessException exception) {
System.out.println(exception);
isSuccess = false;
}
return isSuccess;
}
}
Δημιουργούμε τα repositories OrderRepository, OrderProductRepository.
package springeshop.repositories;
@Repository
public interface OrderRepository extends JpaRepository<Order, Integer> {
@Query("select order from Order order where order.user.id = :userid")
List<Order> findUserOrders(@Param("userid") int userid);
}
package springeshop.repositories;
@Repository
public interface OrderProductRepository extends JpaRepository<OrderProduct, Integer> {
@Query("select prod from OrderProduct prod where prod.order.id = :orderid")
List<Product> findOrderProducts(@Param("orderid") int orderid);
}
Δημιουργούμε τα OrderService, OrderProductService, OrderServiceImpl, OrderProductServiceImpl στο springeshop.service .
package springeshop.service;
public interface OrderService{
boolean saveOrderAndIsSuccess(Order order);
List<Order> findUserOrders(int userid);
}
package springeshop.service;
public interface OrderProductService{
void saveOrderProduct(OrderProduct orderProduct);
boolean saveOrderProducts(List<OrderProduct> orderProducts);
List<Product> findOrderProducts(int orderid);
}
package springeshop.service;
@Service("orderService")
@Transactional
public class OrderServiceImpl implements OrderService{
@Autowired
private OrderRepository orderRepository;
@Override
public boolean saveOrderAndIsSuccess(Order order) {
boolean isSuccess = false;
try {
orderRepository.save(order);
isSuccess = true;
} catch (DataAccessException exception) {
System.out.println(exception);
isSuccess = false;
}
return isSuccess;
}
@Override
public List<Order> findUserOrders(int userid);
return orderRepository.findUserOrders(userid);
}
}
package springeshop.service;
@Service("orderProductService")
@Transactional
public class OrderProductServiceImpl implements OrderProductService{
@Autowired
private OrderProductRepository orderProductRepository;
@Override
public void saveOrderProduct(OrderProduct orderProduct) {
orderProductRepository.save(orderProduct);
}
@Override
public List<Product> findOrderProducts(int orderid) {
return orderProductRepository.findOrderProducts(orderid);
}
@Override
public boolean saveOrderProducts(List<OrderProduct> orderProducts) {
boolean isSuccess = false;
try {
orderProductRepository.saveAll(orderProducts);
isSuccess = true;
} catch (DataAccessException exception) {
System.out.println(exception);
isSuccess = false;
}
return isSuccess;
}
}
Δημιουργούμε τoν OrderApiController στο πακέτο springeshop.controller
package springeshop.controller;
@RestController
@RequestMapping("/api")
public class CartApiController{
@Autowired
private OrderService orderService;
@Autowired
private OrderProductService orderProductService;
@Autowired
private ProductService productService;
@Autowired
private UserService userService;
@Autowired
private ShippingInfoService shippingInfoService;
@Autowired
private BillingInfoService billingInfoService;
@Autowired
private BillingInfoService billingInfoService;
...
Προσθέτουμε τη μέθοδο createOrder() στον OrderApiController, με την οποία προσθέτουμε μια παραγγελία. O client στέλνει ένα OrderDetails αντικείμενο, που περιέχει το καλάθι, το email του χρήστης, τις πληροφορίες χρέωσης και αποστολής. Προσθέτουμε την παραγγελία και τα προϊόντα στους πίνακες και στέλνουμε ένα email με τα στοιχεία της παραγγελίας στο χρήστη.
@RequestMapping(value = "/orders", method = RequestMethod.POST)
public ResponseEntity<?> createCartProduct(@Valid @RequestBody() OrderDetails orderDetails{
boolean isAnonymous = principal == null ? true : false;
if(isAnonymous && orderDetails.getEmail() == null){
return new ResponseEntity<>(new ErrorMessage("Email was not provided" , HttpStatus.BAD_REQUEST);
}
if(shippingInfoService.saveShippingInfoAndIsSuccess(orderDetails.getShipping_info()) &&
billingInfoService.saveBillingInfoAndIsSuccess(orderDetails.getBilling_info())){
Order order = new Order();
if(!isAnonymous){
User user = userService.findByUsername(principal.getName());
order.setUser(user);
}
order.setEmail(orderDetails.getEmail());
order.setStatus("Created");
Timestamp currentDate = new Timestamp(System.currentTimeMillis());
order.setOrder_date(currentDate);
order.setShippingInfo(orderDetails.getShipping_info());
order.setBillingInfo(orderDetails.getBilling_info());
if(orderService.saveOrderAndIsSuccess(order)){
List<OrderProduct> orderProducts = new ArrayList<>();
for(CartProduct cartProduct : orderDetails.getCartProducts()){
OrderProduct orderProduct = new OrderProduct();
OrderProductPrimaryKey id = new OrderProductPrimaryKey(order.getId(), cartProduct.getProductid());
orderProduct.setId(id);
orderProduct.setOrder(order);
orderProduct.setProduct(productService.findById(cartProduct.getProductid()));
orderProduct.setQuantity(cartProduct.getQuantity());
orderProducts.add(orderProduct);
}
if(orderProductService.saveOrderProducts(orderProducts)){
emailService.sendEmail(order, orderDetails.getCartProducts());
return new ResponseEntity<Order>(order, HttpStatus.CREATED);
}
}
}
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
Δημιουργούμε το component checkout-page και το service checkout.
ng generate component checkout-page
ng generate service checkout
Δημιουργούμε τις κλάσεις BillingInfo, ShippingInfo, Order, OrderDetails
checkout.service.ts
Όταν ο χρήστης πατήσει το κουμπί Ολοκλήρωση αγοράς, καλείται η μέθοδος onSubmit(), η οποία καλεί τη μέθοδο addOrder(), ώστε να καταχωρηθεί η παραγγελία στο Server.
checkout-page.component.ts
checkout-page.component.html
checkout-page.component.css
Εμφάνιση σελίδας