package org.hso.ecommerce.controller.shop; import org.hso.ecommerce.action.shop.CreateOrderAction; import org.hso.ecommerce.entities.booking.BookingAccountEntry; import org.hso.ecommerce.entities.booking.PaymentMethod; import org.hso.ecommerce.entities.shop.Address; import org.hso.ecommerce.entities.shop.Article; import org.hso.ecommerce.entities.shop.ShoppingCart; import org.hso.ecommerce.entities.user.User; import org.hso.ecommerce.repos.booking.BookingAccountEntryRepository; import org.hso.ecommerce.repos.booking.BookingRepository; import org.hso.ecommerce.repos.shop.ArticleRepository; import org.hso.ecommerce.repos.shop.CustomerOrderRepository; import org.hso.ecommerce.repos.user.UserRepository; import org.hso.ecommerce.repos.warehouse.WarehouseBookingPositionSlotEntryRepository; import org.hso.ecommerce.repos.warehouse.WarehouseBookingRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.util.ArrayList; import java.util.TreeMap; @Controller @RequestMapping("/shop/") public class ShopCheckoutController { @Autowired private final UserRepository userRepository = null; @Autowired private final ArticleRepository articleRepository = null; @Autowired private final BookingAccountEntryRepository bookingEntryRepository = null; @Autowired private final BookingRepository bookingRepository = null; @Autowired private final WarehouseBookingRepository warehouseBookingRepository = null; @Autowired private final CustomerOrderRepository customerOderRepository = null; @Autowired private final WarehouseBookingPositionSlotEntryRepository wbeseRepo = null; @GetMapping("/checkout") public String shopCheckout(HttpSession session, HttpServletRequest request, @RequestAttribute(value = "shoppingCart") ShoppingCart shoppingCart) { session.setAttribute("afterLogin", request.getRequestURI()); CheckoutListTotals totals = new CheckoutListTotals(); ArrayList items = new ArrayList<>(); boolean inValid = false; for (ShoppingCart.ShoppingCartItem item : shoppingCart.getItems()) { Article article = articleRepository.findById(item.getArticleId()).get(); int inStock = wbeseRepo .getByArticle(item.getArticleId()) .stream() .mapToInt(e -> e.newSumSlot) .sum(); totals.addItem(article, item.getAmount()); items.add(new CheckoutListItem(item.getAmount(), Math.min(inStock, 10), article)); if (item.getAmount() > inStock) { inValid = true; } } request.setAttribute("inValid", inValid); request.setAttribute("checkoutItems", items); request.setAttribute("checkoutTotals", totals); return "shop/checkout"; } public static class CheckoutListTotals { public int net; public TreeMap vatAmounts = new TreeMap<>(); public int total; void addItem(Article article, int amount) { net += article.shopPricePerUnitNetCent * amount; Integer vatPos = vatAmounts.getOrDefault(article.related.vatPercent, 0) + article.getVat() * amount; vatAmounts.put(article.related.vatPercent, vatPos); total += article.getPriceGross() * amount; } } public static class CheckoutListItem { public int amount; public Article article; public int total; public int inStock; public CheckoutListItem(int amount, int inStock, Article article) { this.amount = amount; this.article = article; this.total = amount * article.getPriceGross(); this.inStock = inStock; } } @PostMapping("/checkoutFinish") public String shopCheckoutFinish( HttpSession session, HttpServletRequest request, HttpServletResponse response, @RequestAttribute(value = "user") User user, @RequestAttribute(value = "shoppingCart") ShoppingCart shoppingCart, @RequestParam("address") String address, @RequestParam("cardnumber") String cardnumber, @RequestParam("shopping_cart_revision") Integer cartRevision, @RequestParam("expected_total") Integer expectedPrice ) { if (shoppingCart.getRevision() != cartRevision) { request.setAttribute("error", "Der Warenkorb wurde zwischenzeitlich bearbeitet. Daher konnte der Kaufvorgang nicht abgeschlossen werden. Bitte versuchen Sie es erneut."); response.setStatus(HttpServletResponse.SC_CONFLICT); return "shop/checkout"; } // Must be refetched for persitence. user = userRepository.findById(user.id).get(); CreateOrderAction action = new CreateOrderAction( user, expectedPrice, Address.fromString(address), PaymentMethod.fromCreditCardNumber(cardnumber), bookingEntryRepository.getByUser(user.id).orElse(BookingAccountEntry.newUser(user)), bookingEntryRepository.getByVat().orElse(BookingAccountEntry.newVat()), bookingEntryRepository.getByMain().orElse(BookingAccountEntry.newMain()) ); for (ShoppingCart.ShoppingCartItem item : shoppingCart.getItems()) { Article article = articleRepository.findById(item.getArticleId()).get(); action.addArticle(article, item.getAmount(), wbeseRepo.getByArticle(article.id)); } CreateOrderAction.Result result = null; try { result = action.finish(); customerOderRepository.save(result.customerOrder); bookingRepository.saveAll(result.bookings); warehouseBookingRepository.save(result.warehouseBooking); if (user.defaultPayment == null) { user.defaultPayment = PaymentMethod.fromCreditCardNumber(cardnumber); userRepository.save(user); } shoppingCart.clear(); } catch (CreateOrderAction.ArticleNotInStockException e) { request.setAttribute("error", "Der Artikel '" + e.getArticle().title + "' ist leider nicht mehr in ausreichender Menge verfügbar. Bitte passen Sie die Artikelmenge an."); return shopCheckout(session, request, shoppingCart); } return "shop/checkoutFinish"; } @GetMapping("/checkoutFinish") public String shopCheckoutFinishGET() { return "shop/checkoutFinish"; } }