From f67a23bab9c67a88de76114c83700c745af5375c Mon Sep 17 00:00:00 2001 From: Hannes Date: Fri, 1 May 2020 12:19:52 +0200 Subject: [PATCH 01/28] ShopIndexController initial implementation --- .../hso/ecommerce/app/RequestController.java | 46 +++++------ .../controller/shop/ShopIndexController.java | 77 ++++++++++++++++++- .../main/resources/templates/shop/index.html | 53 ++----------- 3 files changed, 105 insertions(+), 71 deletions(-) diff --git a/prototype/src/main/java/org/hso/ecommerce/app/RequestController.java b/prototype/src/main/java/org/hso/ecommerce/app/RequestController.java index 3602236..defeb1c 100644 --- a/prototype/src/main/java/org/hso/ecommerce/app/RequestController.java +++ b/prototype/src/main/java/org/hso/ecommerce/app/RequestController.java @@ -22,10 +22,10 @@ public class RequestController { static int notSoRandom = 0; - @GetMapping("/") - public String home() { - return "redirect:/shop/"; - } +// @GetMapping("/") +// public String home() { +// return "redirect:/shop/"; +// } @GetMapping("/login") public String login() { @@ -43,7 +43,7 @@ public class RequestController { String gto = (String) session.getAttribute("afterLogin"); Optional user = userRepository.findByEmail(username); - if (user.isEmpty()) { + if (!user.isPresent()) { request.setAttribute("error", "Email Adresse falsch."); response.setStatus(HttpServletResponse.SC_EXPECTATION_FAILED); return "login"; @@ -88,10 +88,10 @@ public class RequestController { return "redirect:/"; } - @GetMapping("/shop/") - public String shop() { - return "shop/index"; - } +// @GetMapping("/shop/") +// public String shop() { +// return "shop/index"; +// } @GetMapping("/shop/search") public String shopSearch() { @@ -137,20 +137,20 @@ public class RequestController { } } - @GetMapping("/about") - public String about() { - return "about"; - } - - @GetMapping("/terms") - public String terms() { - return "terms"; - } - - @GetMapping("/privacy") - public String privacy() { - return "privacy"; - } +// @GetMapping("/about") +// public String about() { +// return "about"; +// } +// +// @GetMapping("/terms") +// public String terms() { +// return "terms"; +// } +// +// @GetMapping("/privacy") +// public String privacy() { +// return "privacy"; +// } @GetMapping("/intern/") diff --git a/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopIndexController.java b/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopIndexController.java index 0f423db..5d442d6 100644 --- a/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopIndexController.java +++ b/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopIndexController.java @@ -1,8 +1,83 @@ package org.hso.ecommerce.controller.shop; +import org.hso.ecommerce.entities.shop.Article; import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; + +import javax.swing.*; +import java.awt.*; +import java.util.ArrayList; @Controller -//@RequestMapping("...") +@RequestMapping("/") public class ShopIndexController { + + @GetMapping("/") + public String home() { + return "redirect:/shop/"; + } + + @GetMapping("/shop/") + public String shop(Model model) { + + ArrayList
dummyArticles = getArticles(); + + model.addAttribute("articles", dummyArticles); + return "shop/index"; + } + + @GetMapping("/about") + public String about() { + return "about"; + } + + @GetMapping("/terms") + public String terms() { + return "terms"; + } + + @GetMapping("/privacy") + public String privacy() { + return "privacy"; + } + + + + public ArrayList
getArticles(){ + ArrayList
dummyArticles = new ArrayList
(); + + Article d1 = new Article(); + d1.description = "this is dummy1"; + d1.title = "dummy1"; + d1.shopPricePerUnitNetCent = 1500; + d1.id = 1234; + dummyArticles.add(d1); + + Article d2 = new Article(); + d2.description = "this is dummy2"; + d2.title = "dummy2"; + d2.shopPricePerUnitNetCent = 2000; + d2.id = 2345; + dummyArticles.add(d2); + + Article d3 = new Article(); + d3.description = "this is dummy3"; + d3.title = "dummy3"; + d3.shopPricePerUnitNetCent = 2500; + d3.id = 3456; + dummyArticles.add(d3); + + Article d4 = new Article(); + d4.description = "this is dummy4"; + d4.title = "dummy4"; + d4.shopPricePerUnitNetCent = 3000; + d4.id = 4567; + dummyArticles.add(d4); + + return dummyArticles; + } + + } diff --git a/prototype/src/main/resources/templates/shop/index.html b/prototype/src/main/resources/templates/shop/index.html index 68a4a1f..a019c8a 100644 --- a/prototype/src/main/resources/templates/shop/index.html +++ b/prototype/src/main/resources/templates/shop/index.html @@ -18,54 +18,13 @@
-
+
+ - -

Lorem Ipsum

-

25.14 EUR

-

- Als Gregor Samsa eines Morgens aus unruhigen Träumen erwachte. -

-
-
-
- - -

Lorem Ipsum

-

10.14 EUR

-

- Als Gregor Samsa eines Morgens aus unruhigen Träumen erwachte. -

-
-
-
- - -

Lorem Ipsum

-

25.14 EUR

-

- Als Gregor Samsa eines Morgens aus unruhigen Träumen erwachte. -

-
-
-
- - -

Lorem Ipsum

-

10.14 EUR

-

- Als Gregor Samsa eines Morgens aus unruhigen Träumen erwachte. -

-
-
-
- - -

Lorem Ipsum

-

44.14 EUR

-

- Als Gregor Samsa eines Morgens aus unruhigen Träumen erwachte. -

+ +

+

+

From 8f081823ca24b5f97ee4ca4d86ef80c0af29b38a Mon Sep 17 00:00:00 2001 From: Hannes Date: Fri, 1 May 2020 14:40:43 +0200 Subject: [PATCH 02/28] ShopIndexController without databasestuff --- .../controller/shop/ShopIndexController.java | 31 ++++++++++++++++--- .../main/resources/templates/shop/index.html | 26 ++++++++++++++-- 2 files changed, 50 insertions(+), 7 deletions(-) diff --git a/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopIndexController.java b/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopIndexController.java index 5d442d6..0be1a50 100644 --- a/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopIndexController.java +++ b/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopIndexController.java @@ -6,6 +6,7 @@ import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; +import javax.servlet.http.HttpSession; import javax.swing.*; import java.awt.*; import java.util.ArrayList; @@ -20,11 +21,32 @@ public class ShopIndexController { } @GetMapping("/shop/") - public String shop(Model model) { + public String shop(Model model, HttpSession session) { - ArrayList
dummyArticles = getArticles(); + //TODO: get commercialised Articles + ArrayList
commercialArticles = getArticles(); + model.addAttribute("commercialArticles", commercialArticles); + + //check if logged in + boolean isLoggedIn = false; + boolean hasOrders = false; + if (session != null && session.getAttribute("id") != null) { + long userId = (long) session.getAttribute("id"); + isLoggedIn = true; + if (false) { + hasOrders = true; //TODO: Find out whether user has orders! + } + } + model.addAttribute("isLoggedIn", isLoggedIn); + model.addAttribute("hasOrders", hasOrders); + + + if (hasOrders) { + //TODO: get up to last 4 Orders + ArrayList
suggestedArticles = getArticles(); + model.addAttribute("suggestedArticles", suggestedArticles); + } - model.addAttribute("articles", dummyArticles); return "shop/index"; } @@ -44,8 +66,7 @@ public class ShopIndexController { } - - public ArrayList
getArticles(){ + public ArrayList
getArticles() { ArrayList
dummyArticles = new ArrayList
(); Article d1 = new Article(); diff --git a/prototype/src/main/resources/templates/shop/index.html b/prototype/src/main/resources/templates/shop/index.html index a019c8a..c3c7535 100644 --- a/prototype/src/main/resources/templates/shop/index.html +++ b/prototype/src/main/resources/templates/shop/index.html @@ -18,7 +18,7 @@
-
+
@@ -38,7 +38,9 @@
From f48f5c40f0486059f319ab7b55a34b75caef2f4b Mon Sep 17 00:00:00 2001 From: Hannes Date: Sat, 2 May 2020 14:38:40 +0200 Subject: [PATCH 03/28] ShopArticleController initial --- .../hso/ecommerce/app/RequestController.java | 46 ++++++------- .../shop/ShopArticleController.java | 69 ++++++++++++++++++- .../resources/templates/shop/articles/id.html | 43 ++++-------- 3 files changed, 105 insertions(+), 53 deletions(-) diff --git a/prototype/src/main/java/org/hso/ecommerce/app/RequestController.java b/prototype/src/main/java/org/hso/ecommerce/app/RequestController.java index 3602236..48c4f18 100644 --- a/prototype/src/main/java/org/hso/ecommerce/app/RequestController.java +++ b/prototype/src/main/java/org/hso/ecommerce/app/RequestController.java @@ -43,7 +43,7 @@ public class RequestController { String gto = (String) session.getAttribute("afterLogin"); Optional user = userRepository.findByEmail(username); - if (user.isEmpty()) { + if (!user.isPresent()) { request.setAttribute("error", "Email Adresse falsch."); response.setStatus(HttpServletResponse.SC_EXPECTATION_FAILED); return "login"; @@ -114,28 +114,28 @@ public class RequestController { return "shop/checkoutFinish"; } - @GetMapping("/shop/articles/{id}") - public String shopArticlesById() { - return "shop/articles/id"; - } - - @PostMapping("/shop/articles/{id}") - public String shopArticlesByIdBuy(HttpSession session, - @RequestAttribute(value = "user", required = false) User customer, - @PathVariable("id") Integer id, - @RequestParam("fastcheckout") Boolean fastcheckout - ) { - if (customer != null) { - if (!fastcheckout) { - return "shop/articles/post_add"; - } else { - return "shop/checkout"; - } - } else { - session.setAttribute("afterLogin", "/shop/articles/" + id); - return "redirect:/login"; - } - } +// @GetMapping("/shop/articles/{id}") +// public String shopArticlesById() { +// return "shop/articles/id"; +// } +// +// @PostMapping("/shop/articles/{id}") +// public String shopArticlesByIdBuy(HttpSession session, +// @RequestAttribute(value = "user", required = false) User customer, +// @PathVariable("id") Integer id, +// @RequestParam("fastcheckout") Boolean fastcheckout +// ) { +// if (customer != null) { +// if (!fastcheckout) { +// return "shop/articles/post_add"; +// } else { +// return "shop/checkout"; +// } +// } else { +// session.setAttribute("afterLogin", "/shop/articles/" + id); +// return "redirect:/login"; +// } +// } @GetMapping("/about") public String about() { diff --git a/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopArticleController.java b/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopArticleController.java index 27ccf63..653286e 100644 --- a/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopArticleController.java +++ b/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopArticleController.java @@ -1,8 +1,75 @@ package org.hso.ecommerce.controller.shop; +import org.hso.ecommerce.entities.shop.Article; +import org.hso.ecommerce.entities.user.User; import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpSession; +import java.util.ArrayList; +import java.util.List; @Controller -//@RequestMapping("...") +@RequestMapping("/shop/articles") public class ShopArticleController { + + @GetMapping("/{id}") + public String shopArticlesById(Model model, @PathVariable("id") Integer Id) { + + //TODO: Get Article by Id instead of this dummy shit + Article d1 = new Article(); + d1.description = "this is dummy1"; + d1.title = "dummy1"; + d1.shopPricePerUnitNetCent = 1500; + d1.id = 1234; + + model.addAttribute("article", d1); + + //TODO: Check if in Stock + if(false){ + model.addAttribute("inStock", true); + }else{ + model.addAttribute("inStock", false); + } + + //TODO: Get 2 Commercialised Articles + List
commercialArticles = new ArrayList
(); + Article d2 = new Article(); + d2.description = "this is dummy2"; + d2.title = "dummy2"; + d2.shopPricePerUnitNetCent = 2000; + d2.id = 2345; + Article d3 = new Article(); + d3.description = "this is dummy3"; + d3.title = "dummy3"; + d3.shopPricePerUnitNetCent = 2500; + d3.id = 3456; + commercialArticles.add(d2); + commercialArticles.add(d3); + model.addAttribute("commercialArticles", commercialArticles); + + return "shop/articles/id"; + } + + @PostMapping("/{id}") + public String shopArticlesByIdBuy(HttpSession session, + @RequestAttribute(value = "user", required = false) User customer, +// @RequestAttribute(value = "shoppingCart", required = true) ShoppingCart shoppingCart, + @PathVariable("id") Integer id, + @RequestParam("fastcheckout") Boolean fastcheckout + ) { + if (customer != null) { + //TODO: Add Article to Shopping Cart + + if (!fastcheckout) { + return "shop/articles/post_add"; + } else { + return "shop/checkout"; + } + } else { + session.setAttribute("afterLogin", "/shop/articles/" + id); + return "redirect:/login"; + } + } } diff --git a/prototype/src/main/resources/templates/shop/articles/id.html b/prototype/src/main/resources/templates/shop/articles/id.html index c99ed1d..2a7df6d 100644 --- a/prototype/src/main/resources/templates/shop/articles/id.html +++ b/prototype/src/main/resources/templates/shop/articles/id.html @@ -19,17 +19,12 @@
-

Tolle Kamera

+

-

25.14 EUR

-

- Eine TOLLE Kamera
- Jaja du denkst jetzt bestimmt: "Bei dem Preis kann sie gar nich sooo TOLL sein".
- Aber glaub mir, sie is echt echt TOLL!
- Indianerehrenwort! -

+

+

@@ -37,14 +32,17 @@
-

50.28 EUR

+

+
-

Auf Lager

+

@@ -56,26 +54,13 @@ - Warenkorb + Warenkorb ()
diff --git a/prototype/src/main/resources/templates/shop/articles/id.html b/prototype/src/main/resources/templates/shop/articles/id.html index 2a7df6d..46b7c93 100644 --- a/prototype/src/main/resources/templates/shop/articles/id.html +++ b/prototype/src/main/resources/templates/shop/articles/id.html @@ -34,10 +34,9 @@

- - From d681f240e1f5adc128d43769bc3fce74db66567e Mon Sep 17 00:00:00 2001 From: CodeSteak Date: Tue, 5 May 2020 18:59:15 +0200 Subject: [PATCH 06/28] implement checkout for non logged in users. --- .../shop/ShopArticleController.java | 9 +- .../shop/ShopCheckoutController.java | 52 ++++++- .../hso/ecommerce/entities/shop/Article.java | 8 + .../ecommerce/entities/shop/ShoppingCart.java | 29 +++- prototype/src/main/resources/db/customers.sql | 7 - .../resources/templates/shop/checkout.html | 141 ++++++------------ 6 files changed, 136 insertions(+), 110 deletions(-) delete mode 100644 prototype/src/main/resources/db/customers.sql diff --git a/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopArticleController.java b/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopArticleController.java index bd544b3..5670f49 100644 --- a/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopArticleController.java +++ b/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopArticleController.java @@ -63,6 +63,7 @@ public class ShopArticleController { @RequestAttribute(value = "shoppingCart") ShoppingCart shoppingCart, @PathVariable("id") Long id, @RequestParam("quantity") Integer quantity, + @RequestParam(value = "set_amount", required = false) Boolean setAmount, @RequestParam("fastcheckout") Boolean fastcheckout ) { @@ -71,12 +72,16 @@ public class ShopArticleController { throw new RuntimeException("Article not found!"); } - shoppingCart.addArticle(article.get(), quantity); + if (setAmount != null && setAmount) { + shoppingCart.setArticleCount(article.get(), quantity); + } else { + shoppingCart.addArticle(article.get(), quantity); + } if (!fastcheckout) { return "shop/articles/post_add"; } else { - return "shop/checkout"; + return "redirect:/shop/checkout"; } } } diff --git a/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopCheckoutController.java b/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopCheckoutController.java index 1573b1b..960a104 100644 --- a/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopCheckoutController.java +++ b/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopCheckoutController.java @@ -1,23 +1,73 @@ package org.hso.ecommerce.controller.shop; +import org.hso.ecommerce.entities.shop.Article; +import org.hso.ecommerce.entities.shop.ShoppingCart; +import org.hso.ecommerce.repos.shop.ArticleRepository; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestAttribute; import org.springframework.web.bind.annotation.RequestMapping; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; +import java.util.ArrayList; +import java.util.TreeMap; @Controller @RequestMapping("/shop/") public class ShopCheckoutController { + @Autowired + private final ArticleRepository articleRepository = null; + @GetMapping("/checkout") - public String shopCheckout(HttpSession session, HttpServletRequest request) { + 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<>(); + for (ShoppingCart.ShoppingCartItem item : shoppingCart.getItems()) { + Article article = articleRepository.findById(item.getArticleId()).get(); + + totals.addItem(article, item.getAmount()); + items.add(new CheckoutListItem(item.getAmount(), article)); + } + + 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 CheckoutListItem(int amount, Article article) { + this.amount = amount; + this.article = article; + this.total = amount * article.getPriceGross(); + } + } + @PostMapping("/checkoutFinish") public String shopCheckoutFinish() { return "shop/checkoutFinish"; diff --git a/prototype/src/main/java/org/hso/ecommerce/entities/shop/Article.java b/prototype/src/main/java/org/hso/ecommerce/entities/shop/Article.java index 6cd198e..2e066cd 100644 --- a/prototype/src/main/java/org/hso/ecommerce/entities/shop/Article.java +++ b/prototype/src/main/java/org/hso/ecommerce/entities/shop/Article.java @@ -37,4 +37,12 @@ public class Article { @ManyToMany @JoinTable(name = "article_categories_bindings") public Set categories = new HashSet<>(); + + public int getVat() { + return (shopPricePerUnitNetCent * related.vatPercent) / 100; + } + + public int getPriceGross() { + return shopPricePerUnitNetCent + getVat(); + } } diff --git a/prototype/src/main/java/org/hso/ecommerce/entities/shop/ShoppingCart.java b/prototype/src/main/java/org/hso/ecommerce/entities/shop/ShoppingCart.java index f7955ec..aee94c2 100644 --- a/prototype/src/main/java/org/hso/ecommerce/entities/shop/ShoppingCart.java +++ b/prototype/src/main/java/org/hso/ecommerce/entities/shop/ShoppingCart.java @@ -1,6 +1,7 @@ package org.hso.ecommerce.entities.shop; import java.util.ArrayList; +import java.util.List; // Not a db entity. Just for session storage public class ShoppingCart { @@ -13,6 +14,10 @@ public class ShoppingCart { items = new ArrayList<>(); } + public List getItems() { + return items; + } + public int getItemCount() { int count = 0; @@ -40,7 +45,25 @@ public class ShoppingCart { items.add(new ShoppingCartItem(quantity, article)); } - private static class ShoppingCartItem { + public void setArticleCount(Article article, Integer quantity) { + this.revision++; + + boolean found = false; + for (ShoppingCartItem i : items) { + if (i.getArticleId() == article.id) { + i.setAmount(quantity); + found = true; + break; + } + } + if (!found) { + items.add(new ShoppingCartItem(quantity, article)); + } + + items.removeIf(i -> i.getAmount() == 0); + } + + public static class ShoppingCartItem { private int amount; private final long articleId; @@ -60,5 +83,9 @@ public class ShoppingCart { public long getArticleId() { return articleId; } + + public void setAmount(Integer amount) { + this.amount = amount; + } } } diff --git a/prototype/src/main/resources/db/customers.sql b/prototype/src/main/resources/db/customers.sql deleted file mode 100644 index b1a108f..0000000 --- a/prototype/src/main/resources/db/customers.sql +++ /dev/null @@ -1,7 +0,0 @@ -CREATE TABLE "customers" ( - "id" INTEGER PRIMARY KEY AUTOINCREMENT, - "lastname" TEXT, - "firstname" TEXT, - "username" TEXT, - "password" TEXT -); diff --git a/prototype/src/main/resources/templates/shop/checkout.html b/prototype/src/main/resources/templates/shop/checkout.html index e6bb15d..e017f9e 100644 --- a/prototype/src/main/resources/templates/shop/checkout.html +++ b/prototype/src/main/resources/templates/shop/checkout.html @@ -31,91 +31,31 @@ Menge - - - Kamera - 100,50 EUR - - - - - - - - - - Earbuds - 63,95 EUR - - - - - - - - - - USB-Magic Light - 11,90 EUR - - - - - - - - - - 3D Magic Stativ - 15,99 EUR - - - - - - - - - - Ersatzfernbedinung - 7,95 EUR - - - - - - - + + + + + EUR + +
+ + + + +
+ + +
@@ -151,23 +91,26 @@ Musterstraße 42 - - - - - - - - - - - - - + + + + + + + - + From b2f927e48d2da3bc39c5c6a8833d6735534f2c71 Mon Sep 17 00:00:00 2001 From: CodeSteak Date: Tue, 5 May 2020 22:56:12 +0200 Subject: [PATCH 07/28] Implement CreateCustomerOrderAction; Not implemented: correct booking and WarehouseBooking fetching... Puhh, that was a struggle to get working. Damn JPA Shit --- prototype/scripts/addusers.sql | 12 +- .../action/booking/CreateBookingAction.java | 30 +++ .../action/shop/CreateOrderAction.java | 177 ++++++++++++++++++ .../action/shop/EnableTrackingAction.java | 11 ++ .../action/somepackage/DemoAction.java | 7 - .../shop/ShopCheckoutController.java | 73 +++++++- .../ecommerce/entities/booking/Booking.java | 6 +- .../entities/booking/BookingAccountEntry.java | 40 +++- .../entities/booking/BookingReason.java | 15 +- .../entities/booking/PaymentMethod.java | 7 + .../hso/ecommerce/entities/shop/Address.java | 21 ++- .../entities/shop/CustomerOrder.java | 2 +- .../ecommerce/entities/shop/ShoppingCart.java | 16 +- .../org/hso/ecommerce/entities/user/User.java | 4 +- .../entities/warehouse/WarehouseBooking.java | 7 +- .../warehouse/WarehouseBookingPosition.java | 8 +- .../WarehouseBookingPositionSlotEntry.java | 19 +- .../warehouse/WarehouseBookingReason.java | 7 + .../BookingAccountEntryRepository.java | 26 +++ .../repos/booking/BookingRepository.java | 12 ++ .../repos/shop/CustomerOderRepository.java | 11 ++ ...useBookingPositionSlotEntryRepository.java | 18 ++ .../warehouse/WarehouseBookingRepository.java | 11 ++ .../resources/templates/shop/checkout.html | 39 ++-- 24 files changed, 526 insertions(+), 53 deletions(-) create mode 100644 prototype/src/main/java/org/hso/ecommerce/action/booking/CreateBookingAction.java create mode 100644 prototype/src/main/java/org/hso/ecommerce/action/shop/CreateOrderAction.java create mode 100644 prototype/src/main/java/org/hso/ecommerce/action/shop/EnableTrackingAction.java delete mode 100644 prototype/src/main/java/org/hso/ecommerce/action/somepackage/DemoAction.java create mode 100644 prototype/src/main/java/org/hso/ecommerce/repos/booking/BookingAccountEntryRepository.java create mode 100644 prototype/src/main/java/org/hso/ecommerce/repos/booking/BookingRepository.java create mode 100644 prototype/src/main/java/org/hso/ecommerce/repos/shop/CustomerOderRepository.java create mode 100644 prototype/src/main/java/org/hso/ecommerce/repos/warehouse/WarehouseBookingPositionSlotEntryRepository.java create mode 100644 prototype/src/main/java/org/hso/ecommerce/repos/warehouse/WarehouseBookingRepository.java diff --git a/prototype/scripts/addusers.sql b/prototype/scripts/addusers.sql index 86b6d43..db3d6ed 100644 --- a/prototype/scripts/addusers.sql +++ b/prototype/scripts/addusers.sql @@ -1,9 +1,9 @@ /* password is 123 */ -INSERT INTO users ("created", "email", "password_hash", "gets_ads", "is_active", "is_employee", "isb2b") -VALUES (datetime('now','localtime') ||'.0', "emp@ecom", "$2a$10$zFiqcePBmXHErD86vkI.vO1dnX20ezoVSM8xjGi59nktXYQv0o.fK", "0", "1", "1", "0"); +INSERT INTO users ("created", "email", "password_hash", "is_active", "is_employee") +VALUES (datetime('now','localtime') ||'.0', "emp@ecom", "$2a$10$zFiqcePBmXHErD86vkI.vO1dnX20ezoVSM8xjGi59nktXYQv0o.fK", "1", "1"); -INSERT INTO users ("created", "email", "password_hash", "gets_ads", "is_active", "is_employee", "isb2b") -VALUES (datetime('now','localtime') ||'.0', "user@ecom", "$2a$10$zFiqcePBmXHErD86vkI.vO1dnX20ezoVSM8xjGi59nktXYQv0o.fK", "1", "1", "0", "0"); +INSERT INTO users ("created", "email", "password_hash", "is_active", "is_employee") +VALUES (datetime('now','localtime') ||'.0', "user@ecom", "$2a$10$zFiqcePBmXHErD86vkI.vO1dnX20ezoVSM8xjGi59nktXYQv0o.fK", "1", "0"); -INSERT INTO users ("created", "email", "password_hash", "gets_ads", "is_active", "is_employee", "isb2b") -VALUES (datetime('now','localtime') ||'.0', "blocked@ecom", "$2a$10$zFiqcePBmXHErD86vkI.vO1dnX20ezoVSM8xjGi59nktXYQv0o.fK", "1", "0", "0", "0"); \ No newline at end of file +INSERT INTO users ("created", "email", "password_hash", "is_active", "is_employee") +VALUES (datetime('now','localtime') ||'.0', "blocked@ecom", "$2a$10$zFiqcePBmXHErD86vkI.vO1dnX20ezoVSM8xjGi59nktXYQv0o.fK", "0", "0"); \ No newline at end of file diff --git a/prototype/src/main/java/org/hso/ecommerce/action/booking/CreateBookingAction.java b/prototype/src/main/java/org/hso/ecommerce/action/booking/CreateBookingAction.java new file mode 100644 index 0000000..f01e6a3 --- /dev/null +++ b/prototype/src/main/java/org/hso/ecommerce/action/booking/CreateBookingAction.java @@ -0,0 +1,30 @@ +package org.hso.ecommerce.action.booking; + +import org.hso.ecommerce.entities.booking.Booking; +import org.hso.ecommerce.entities.booking.BookingAccountEntry; +import org.hso.ecommerce.entities.booking.BookingReason; + +public class CreateBookingAction { + + private Booking booking; + + public CreateBookingAction(BookingAccountEntry source, BookingAccountEntry destination, BookingReason reason, int amountCent) { + booking = new Booking(); + booking.reason = reason; + booking.amountCent = amountCent; + + assert source != null || destination != null; + + if (source != null) { + booking.source = source.copyAddAmount(-amountCent); + } + if (destination != null) { + booking.destination = destination.copyAddAmount(amountCent); + } + + } + + public Booking finish() { + return booking; + } +} diff --git a/prototype/src/main/java/org/hso/ecommerce/action/shop/CreateOrderAction.java b/prototype/src/main/java/org/hso/ecommerce/action/shop/CreateOrderAction.java new file mode 100644 index 0000000..ed1066c --- /dev/null +++ b/prototype/src/main/java/org/hso/ecommerce/action/shop/CreateOrderAction.java @@ -0,0 +1,177 @@ +package org.hso.ecommerce.action.shop; + +import org.hso.ecommerce.action.booking.CreateBookingAction; +import org.hso.ecommerce.entities.booking.*; +import org.hso.ecommerce.entities.shop.Address; +import org.hso.ecommerce.entities.shop.Article; +import org.hso.ecommerce.entities.shop.CustomerOrder; +import org.hso.ecommerce.entities.shop.CustomerOrderPosition; +import org.hso.ecommerce.entities.user.User; +import org.hso.ecommerce.entities.warehouse.WarehouseBooking; +import org.hso.ecommerce.entities.warehouse.WarehouseBookingPosition; +import org.hso.ecommerce.entities.warehouse.WarehouseBookingPositionSlotEntry; + +import java.sql.Timestamp; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +public class CreateOrderAction { + + private User user; + Address destination; + + private int expectedTotalGrossCent; + + private int totalNetCent; + private int totalVatCent; + private PaymentMethod method; + + private BookingAccountEntry latestUserBooking; + private BookingAccountEntry latestVatBooking; + private BookingAccountEntry latestMainBooking; + + private List orderItems = new ArrayList<>(); + + public CreateOrderAction( + User user, + int expectedTotalGrossCent, + Address destination, + PaymentMethod method, + BookingAccountEntry latestUserBooking, + BookingAccountEntry latestVatBooking, + BookingAccountEntry latestMainBooking + ) { + this.user = user; + this.expectedTotalGrossCent = expectedTotalGrossCent; + this.destination = destination; + this.method = method; + + this.latestUserBooking = latestUserBooking; + assert latestUserBooking.userAccount.id == user.id; + + this.latestVatBooking = latestVatBooking; + assert latestVatBooking.isVATAccount; + + this.latestMainBooking = latestMainBooking; + assert latestMainBooking.isMainAccount; + } + + public void addArticle(Article article, int quantity, List availableSlots) { + for (WarehouseBookingPositionSlotEntry slot : availableSlots) { + assert slot.article.id == article.id; + } + + orderItems.add(new OrderItem(article, availableSlots, quantity)); + + totalNetCent += article.shopPricePerUnitNetCent * quantity; + totalVatCent += article.getVat() * quantity; + } + + public Result finish() { + CustomerOrder order = createOrder(); + CustomerPayment payment = createPayment(); + + List bookingList = new ArrayList<>(); + bookingList.add(new CreateBookingAction(latestUserBooking, latestMainBooking, new BookingReason(order), order.totalGrossCent).finish()); + bookingList.add(new CreateBookingAction(null, latestUserBooking, new BookingReason(payment), order.totalGrossCent).finish()); + bookingList.add(new CreateBookingAction(latestMainBooking, latestVatBooking, new BookingReason(order), order.totalVatCent).finish()); + + WarehouseBooking warehouseBooking = createWarehouseBooking(order); + + return new Result( + order, + warehouseBooking, + bookingList + ); + } + + private WarehouseBooking createWarehouseBooking(CustomerOrder order) { + WarehouseBooking booking = new WarehouseBooking(); + booking.created = new Timestamp(new Date().getTime()); + booking.reason = new BookingReason(order); + + for (OrderItem item : orderItems) { + int needed = item.quantity; + + for (WarehouseBookingPositionSlotEntry slot : item.availableSlots) { + int remove = Math.min(slot.newSumSlot, needed); + needed -= remove; + + WarehouseBookingPosition bookingPosition = new WarehouseBookingPosition(); + + bookingPosition.article = item.article; + bookingPosition.amount = -remove; + bookingPosition.slotEntry = slot.copyAddAmount(-remove); + bookingPosition.booking = booking; + + booking.positions.add(bookingPosition); + + if (needed == 0) { + break; + } + } + } + + return booking; + } + + private CustomerPayment createPayment() { + CustomerPayment payment = new CustomerPayment(); + payment.amountCent = totalNetCent + totalVatCent; + payment.payment = method; + return payment; + } + + + private CustomerOrder createOrder() { + assert totalNetCent + totalVatCent == expectedTotalGrossCent; + + CustomerOrder customerOrder = new CustomerOrder(); + customerOrder.customer = user; + customerOrder.destination = destination; + + for (OrderItem item : orderItems) { + CustomerOrderPosition position = new CustomerOrderPosition(); + position.article = item.article; + position.pricePerUnit = item.article.shopPricePerUnitNetCent; + position.quantity = item.quantity; + + position.order = customerOrder; + + customerOrder.positions.add(position); + } + + customerOrder.created = new Timestamp(new Date().getTime()); + + customerOrder.totalNetCent = totalNetCent; + customerOrder.totalVatCent = totalVatCent; + customerOrder.totalGrossCent = totalNetCent + totalVatCent; + + return customerOrder; + } + + public static class Result { + public final CustomerOrder customerOrder; + public final WarehouseBooking warehouseBooking; + public final List bookings; + + Result(CustomerOrder customerOrder, WarehouseBooking warehouseBooking, List bookings) { + this.customerOrder = customerOrder; + this.warehouseBooking = warehouseBooking; + this.bookings = bookings; + } + } + + private static class OrderItem { + List availableSlots; + int quantity; + Article article; + + public OrderItem(Article article, List availableSlots, int quantity) { + this.article = article; + this.availableSlots = availableSlots; + this.quantity = quantity; + } + } +} diff --git a/prototype/src/main/java/org/hso/ecommerce/action/shop/EnableTrackingAction.java b/prototype/src/main/java/org/hso/ecommerce/action/shop/EnableTrackingAction.java new file mode 100644 index 0000000..d3e2dc7 --- /dev/null +++ b/prototype/src/main/java/org/hso/ecommerce/action/shop/EnableTrackingAction.java @@ -0,0 +1,11 @@ +package org.hso.ecommerce.action.shop; + +import org.hso.ecommerce.entities.shop.CustomerOrder; + +public class EnableTrackingAction { + + public static void addTrackingInfo(CustomerOrder customerOrder) { + // TODO: + customerOrder.trackingId = "555-NASE"; + } +} diff --git a/prototype/src/main/java/org/hso/ecommerce/action/somepackage/DemoAction.java b/prototype/src/main/java/org/hso/ecommerce/action/somepackage/DemoAction.java deleted file mode 100644 index 22f8946..0000000 --- a/prototype/src/main/java/org/hso/ecommerce/action/somepackage/DemoAction.java +++ /dev/null @@ -1,7 +0,0 @@ -package org.hso.ecommerce.action.somepackage; - -public class DemoAction { - // TODO: remove me. - // mksubpackage - -} diff --git a/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopCheckoutController.java b/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopCheckoutController.java index 960a104..66ced97 100644 --- a/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopCheckoutController.java +++ b/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopCheckoutController.java @@ -1,14 +1,23 @@ package org.hso.ecommerce.controller.shop; +import org.hso.ecommerce.action.shop.CreateOrderAction; +import org.hso.ecommerce.action.shop.EnableTrackingAction; +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.CustomerOderRepository; +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.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestAttribute; -import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; @@ -19,9 +28,27 @@ import java.util.TreeMap; @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 CustomerOderRepository customerOderRepository = null; + + @Autowired + private final WarehouseBookingPositionSlotEntryRepository wbeseRepo = null; + @GetMapping("/checkout") public String shopCheckout(HttpSession session, HttpServletRequest request, @@ -69,7 +96,43 @@ public class ShopCheckoutController { } @PostMapping("/checkoutFinish") - public String shopCheckoutFinish() { + public String shopCheckoutFinish( + @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 + ) { + + // Must be refetched for persitence. + user = userRepository.findById(user.id).get(); + + CreateOrderAction action = new CreateOrderAction( + user, + expectedPrice, + Address.fromString(address), + PaymentMethod.fromCreditCarNumber(cardnumber), + bookingEntryRepository.getByUser(user).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)); + } + + CreateOrderAction.Result result = action.finish(); + + EnableTrackingAction.addTrackingInfo(result.customerOrder); + + customerOderRepository.save(result.customerOrder); + bookingRepository.saveAll(result.bookings); + warehouseBookingRepository.save(result.warehouseBooking); + + shoppingCart.clear(); + return "shop/checkoutFinish"; } diff --git a/prototype/src/main/java/org/hso/ecommerce/entities/booking/Booking.java b/prototype/src/main/java/org/hso/ecommerce/entities/booking/Booking.java index 997f578..e61ea07 100644 --- a/prototype/src/main/java/org/hso/ecommerce/entities/booking/Booking.java +++ b/prototype/src/main/java/org/hso/ecommerce/entities/booking/Booking.java @@ -14,12 +14,12 @@ public class Booking { // always >= 0 public int amountCent; - @ManyToOne(optional = true) + @ManyToOne(optional = true, cascade = CascadeType.ALL) public BookingAccountEntry source; - @ManyToOne(optional = true) + @ManyToOne(optional = true, cascade = CascadeType.ALL) public BookingAccountEntry destination; - @OneToOne(optional = false) + @OneToOne(optional = false, cascade = CascadeType.ALL) public BookingReason reason; } diff --git a/prototype/src/main/java/org/hso/ecommerce/entities/booking/BookingAccountEntry.java b/prototype/src/main/java/org/hso/ecommerce/entities/booking/BookingAccountEntry.java index 92e282f..04b3b8a 100644 --- a/prototype/src/main/java/org/hso/ecommerce/entities/booking/BookingAccountEntry.java +++ b/prototype/src/main/java/org/hso/ecommerce/entities/booking/BookingAccountEntry.java @@ -16,13 +16,49 @@ public class BookingAccountEntry { public int newSumCent; - @ManyToOne(optional = true) + @ManyToOne(optional = true, cascade = CascadeType.ALL) public User userAccount; - @ManyToOne(optional = true) + @ManyToOne(optional = true, cascade = CascadeType.ALL) public Supplier supplierAccount; public boolean isMainAccount; public boolean isVATAccount; + public BookingAccountEntry copyAddAmount(int amountCent) { + BookingAccountEntry e = new BookingAccountEntry(); + + e.userAccount = userAccount; + e.supplierAccount = supplierAccount; + e.isMainAccount = isMainAccount; + e.isVATAccount = isVATAccount; + + e.newSumCent = newSumCent + amountCent; + + return e; + } + + public static BookingAccountEntry newUser(User user) { + BookingAccountEntry e = new BookingAccountEntry(); + e.userAccount = user; + e.newSumCent = 0; + + return e; + } + + public static BookingAccountEntry newMain() { + BookingAccountEntry e = new BookingAccountEntry(); + e.isMainAccount = true; + e.newSumCent = 0; + + return e; + } + + public static BookingAccountEntry newVat() { + BookingAccountEntry e = new BookingAccountEntry(); + e.isVATAccount = true; + e.newSumCent = 0; + + return e; + } } diff --git a/prototype/src/main/java/org/hso/ecommerce/entities/booking/BookingReason.java b/prototype/src/main/java/org/hso/ecommerce/entities/booking/BookingReason.java index b2bc6cc..f973d26 100644 --- a/prototype/src/main/java/org/hso/ecommerce/entities/booking/BookingReason.java +++ b/prototype/src/main/java/org/hso/ecommerce/entities/booking/BookingReason.java @@ -22,9 +22,22 @@ public class BookingReason { @ManyToOne(optional = true) public CustomerOrder customerOrder; - @ManyToOne(optional = true) + @OneToOne(optional = true, cascade = CascadeType.ALL) public CustomerPayment customerPayment; @ManyToOne(optional = true) public SupplierOrder supplierOrder; + + public BookingReason() { + } + + ; + + public BookingReason(CustomerOrder order) { + this.customerOrder = order; + } + + public BookingReason(CustomerPayment customerPayment) { + this.customerPayment = customerPayment; + } } diff --git a/prototype/src/main/java/org/hso/ecommerce/entities/booking/PaymentMethod.java b/prototype/src/main/java/org/hso/ecommerce/entities/booking/PaymentMethod.java index 6cb5307..4f81062 100644 --- a/prototype/src/main/java/org/hso/ecommerce/entities/booking/PaymentMethod.java +++ b/prototype/src/main/java/org/hso/ecommerce/entities/booking/PaymentMethod.java @@ -7,4 +7,11 @@ import javax.validation.constraints.NotNull; public class PaymentMethod { @NotNull public String creditCardNumber; + + public static PaymentMethod fromCreditCarNumber(String cardnumber) { + PaymentMethod m = new PaymentMethod(); + m.creditCardNumber = cardnumber; + + return m; + } } diff --git a/prototype/src/main/java/org/hso/ecommerce/entities/shop/Address.java b/prototype/src/main/java/org/hso/ecommerce/entities/shop/Address.java index 32d057b..2f76083 100644 --- a/prototype/src/main/java/org/hso/ecommerce/entities/shop/Address.java +++ b/prototype/src/main/java/org/hso/ecommerce/entities/shop/Address.java @@ -4,7 +4,24 @@ import javax.persistence.Embeddable; @Embeddable public class Address { - public String name; - public String addressString; + public String name = ""; + public String addressString = ""; public String country = "DE"; + + @Override + public String toString() { + return name + "\n" + addressString; + } + + public static Address fromString(String addr) { + Address a = new Address(); + + String[] arr = addr.split("\n", 2); + a.name = arr[0]; + if (arr.length > 1) { + a.addressString = arr[1]; + } + + return a; + } } diff --git a/prototype/src/main/java/org/hso/ecommerce/entities/shop/CustomerOrder.java b/prototype/src/main/java/org/hso/ecommerce/entities/shop/CustomerOrder.java index dd7d4f8..1b20bb2 100644 --- a/prototype/src/main/java/org/hso/ecommerce/entities/shop/CustomerOrder.java +++ b/prototype/src/main/java/org/hso/ecommerce/entities/shop/CustomerOrder.java @@ -24,7 +24,7 @@ public class CustomerOrder { @OneToMany( targetEntity = CustomerOrderPosition.class, - mappedBy = "order" + mappedBy = "order", cascade = CascadeType.ALL ) public List positions = new ArrayList<>(); diff --git a/prototype/src/main/java/org/hso/ecommerce/entities/shop/ShoppingCart.java b/prototype/src/main/java/org/hso/ecommerce/entities/shop/ShoppingCart.java index aee94c2..d059f15 100644 --- a/prototype/src/main/java/org/hso/ecommerce/entities/shop/ShoppingCart.java +++ b/prototype/src/main/java/org/hso/ecommerce/entities/shop/ShoppingCart.java @@ -6,12 +6,18 @@ import java.util.List; // Not a db entity. Just for session storage public class ShoppingCart { + private final static int MAX_ITEMS = 10; + private int revision; private ArrayList items; public ShoppingCart() { - revision = (int) Math.round(Math.random() * 0xFFFF); + clear(); + } + + public void clear() { items = new ArrayList<>(); + revision = (int) Math.round(Math.random() * 0xFFFF); } public List getItems() { @@ -60,7 +66,7 @@ public class ShoppingCart { items.add(new ShoppingCartItem(quantity, article)); } - items.removeIf(i -> i.getAmount() == 0); + items.removeIf(i -> i.getAmount() <= 0); } public static class ShoppingCartItem { @@ -78,6 +84,9 @@ public class ShoppingCart { public void addAmount(int amount) { this.amount += amount; + if (this.amount > MAX_ITEMS) { + this.amount = MAX_ITEMS; + } } public long getArticleId() { @@ -86,6 +95,9 @@ public class ShoppingCart { public void setAmount(Integer amount) { this.amount = amount; + if (this.amount > MAX_ITEMS) { + this.amount = MAX_ITEMS; + } } } } diff --git a/prototype/src/main/java/org/hso/ecommerce/entities/user/User.java b/prototype/src/main/java/org/hso/ecommerce/entities/user/User.java index 9b07996..784d89a 100644 --- a/prototype/src/main/java/org/hso/ecommerce/entities/user/User.java +++ b/prototype/src/main/java/org/hso/ecommerce/entities/user/User.java @@ -30,10 +30,10 @@ public class User { public boolean isEmployee; @Embedded - private Address defaultDeliveryAddress; + public Address defaultDeliveryAddress; @Embedded - private PaymentMethod defaultPayment; + public PaymentMethod defaultPayment; public long getId() { return id; diff --git a/prototype/src/main/java/org/hso/ecommerce/entities/warehouse/WarehouseBooking.java b/prototype/src/main/java/org/hso/ecommerce/entities/warehouse/WarehouseBooking.java index 97a2805..cf60734 100644 --- a/prototype/src/main/java/org/hso/ecommerce/entities/warehouse/WarehouseBooking.java +++ b/prototype/src/main/java/org/hso/ecommerce/entities/warehouse/WarehouseBooking.java @@ -1,5 +1,7 @@ package org.hso.ecommerce.entities.warehouse; +import org.hso.ecommerce.entities.booking.BookingReason; + import javax.persistence.*; import javax.validation.constraints.NotNull; import java.util.ArrayList; @@ -21,7 +23,10 @@ public class WarehouseBooking { public boolean isDone; @OneToMany( - mappedBy = "booking" + mappedBy = "booking", cascade = CascadeType.ALL ) public List positions = new ArrayList<>(); + + @OneToOne(optional = false, cascade = CascadeType.ALL) + public BookingReason reason; } diff --git a/prototype/src/main/java/org/hso/ecommerce/entities/warehouse/WarehouseBookingPosition.java b/prototype/src/main/java/org/hso/ecommerce/entities/warehouse/WarehouseBookingPosition.java index 88ceee3..e3a147a 100644 --- a/prototype/src/main/java/org/hso/ecommerce/entities/warehouse/WarehouseBookingPosition.java +++ b/prototype/src/main/java/org/hso/ecommerce/entities/warehouse/WarehouseBookingPosition.java @@ -23,10 +23,6 @@ public class WarehouseBookingPosition { public int amount; // positive or negative - @ManyToOne(optional = true) - public WarehouseBookingPositionSlotEntry source; - - @ManyToOne(optional = true) - public WarehouseBookingPositionSlotEntry destination; - + @ManyToOne(optional = true, cascade = CascadeType.ALL) + public WarehouseBookingPositionSlotEntry slotEntry; } diff --git a/prototype/src/main/java/org/hso/ecommerce/entities/warehouse/WarehouseBookingPositionSlotEntry.java b/prototype/src/main/java/org/hso/ecommerce/entities/warehouse/WarehouseBookingPositionSlotEntry.java index 7529e4f..d9ca4c6 100644 --- a/prototype/src/main/java/org/hso/ecommerce/entities/warehouse/WarehouseBookingPositionSlotEntry.java +++ b/prototype/src/main/java/org/hso/ecommerce/entities/warehouse/WarehouseBookingPositionSlotEntry.java @@ -16,8 +16,23 @@ public class WarehouseBookingPositionSlotEntry { @ManyToOne public Article article; - public int newSumArticles; - public int newSumWarehousePosition; + // Can;t do, does not work when created in action. + //public int newSumArticles; + public int newSumSlot; public int slot; + + public WarehouseBookingPositionSlotEntry copyAddAmount(int amount) { + WarehouseBookingPositionSlotEntry e = new WarehouseBookingPositionSlotEntry(); + + e.article = article; + e.slot = slot; + + e.newSumSlot = newSumSlot + amount; + + assert e.article.warehouseUnitsPerSlot >= e.newSumSlot; + assert e.newSumSlot >= 0; + + return e; + } } diff --git a/prototype/src/main/java/org/hso/ecommerce/entities/warehouse/WarehouseBookingReason.java b/prototype/src/main/java/org/hso/ecommerce/entities/warehouse/WarehouseBookingReason.java index ec60c4d..08ee80a 100644 --- a/prototype/src/main/java/org/hso/ecommerce/entities/warehouse/WarehouseBookingReason.java +++ b/prototype/src/main/java/org/hso/ecommerce/entities/warehouse/WarehouseBookingReason.java @@ -23,4 +23,11 @@ public class WarehouseBookingReason { public CustomerOrder customerOrder; public boolean isManuel; + + public WarehouseBookingReason() { + } + + public WarehouseBookingReason(CustomerOrder order) { + this.customerOrder = order; + } } diff --git a/prototype/src/main/java/org/hso/ecommerce/repos/booking/BookingAccountEntryRepository.java b/prototype/src/main/java/org/hso/ecommerce/repos/booking/BookingAccountEntryRepository.java new file mode 100644 index 0000000..657e34d --- /dev/null +++ b/prototype/src/main/java/org/hso/ecommerce/repos/booking/BookingAccountEntryRepository.java @@ -0,0 +1,26 @@ +package org.hso.ecommerce.repos.booking; + +import org.hso.ecommerce.entities.booking.BookingAccountEntry; +import org.hso.ecommerce.entities.user.User; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.stereotype.Repository; + +import java.util.Optional; + +@Repository +public interface BookingAccountEntryRepository extends JpaRepository { + + @Query("SELECT e FROM BookingAccountEntry e WHERE e.userAccount = :user ORDER BY e.id DESC") + Optional getByUser(User user); + + @Query("SELECT e FROM BookingAccountEntry e WHERE e.isMainAccount = 1 ORDER BY e.id DESC") + Optional getByMain(); + + @Query("SELECT e FROM BookingAccountEntry e WHERE e.isVATAccount = 1 ORDER BY e.id DESC") + Optional getByVat(); + + +} + + diff --git a/prototype/src/main/java/org/hso/ecommerce/repos/booking/BookingRepository.java b/prototype/src/main/java/org/hso/ecommerce/repos/booking/BookingRepository.java new file mode 100644 index 0000000..454b3f3 --- /dev/null +++ b/prototype/src/main/java/org/hso/ecommerce/repos/booking/BookingRepository.java @@ -0,0 +1,12 @@ +package org.hso.ecommerce.repos.booking; + +import org.hso.ecommerce.entities.booking.Booking; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface BookingRepository extends JpaRepository { + +} + + diff --git a/prototype/src/main/java/org/hso/ecommerce/repos/shop/CustomerOderRepository.java b/prototype/src/main/java/org/hso/ecommerce/repos/shop/CustomerOderRepository.java new file mode 100644 index 0000000..407f45c --- /dev/null +++ b/prototype/src/main/java/org/hso/ecommerce/repos/shop/CustomerOderRepository.java @@ -0,0 +1,11 @@ +package org.hso.ecommerce.repos.shop; + +import org.hso.ecommerce.entities.shop.CustomerOrder; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface CustomerOderRepository extends JpaRepository { + +} + diff --git a/prototype/src/main/java/org/hso/ecommerce/repos/warehouse/WarehouseBookingPositionSlotEntryRepository.java b/prototype/src/main/java/org/hso/ecommerce/repos/warehouse/WarehouseBookingPositionSlotEntryRepository.java new file mode 100644 index 0000000..839a017 --- /dev/null +++ b/prototype/src/main/java/org/hso/ecommerce/repos/warehouse/WarehouseBookingPositionSlotEntryRepository.java @@ -0,0 +1,18 @@ +package org.hso.ecommerce.repos.warehouse; + +import org.hso.ecommerce.entities.shop.Article; +import org.hso.ecommerce.entities.warehouse.WarehouseBookingPositionSlotEntry; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Repository +public interface WarehouseBookingPositionSlotEntryRepository extends JpaRepository { + + // TODO this is wrong. revisit. + @Query("SELECT e FROM WarehouseBookingPositionSlotEntry e WHERE e.article = :article ORDER BY e.id DESC") + List getByArticle(Article article); +} + diff --git a/prototype/src/main/java/org/hso/ecommerce/repos/warehouse/WarehouseBookingRepository.java b/prototype/src/main/java/org/hso/ecommerce/repos/warehouse/WarehouseBookingRepository.java new file mode 100644 index 0000000..8d01092 --- /dev/null +++ b/prototype/src/main/java/org/hso/ecommerce/repos/warehouse/WarehouseBookingRepository.java @@ -0,0 +1,11 @@ +package org.hso.ecommerce.repos.warehouse; + +import org.hso.ecommerce.entities.warehouse.WarehouseBooking; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface WarehouseBookingRepository extends JpaRepository { + +} + diff --git a/prototype/src/main/resources/templates/shop/checkout.html b/prototype/src/main/resources/templates/shop/checkout.html index e017f9e..cf02b5c 100644 --- a/prototype/src/main/resources/templates/shop/checkout.html +++ b/prototype/src/main/resources/templates/shop/checkout.html @@ -21,7 +21,17 @@ -
+
+
+

Noch keine Artikel im Warenkorb.

+

+ +

+ Weiter shoppen +
+ +
+
Artikel (Netto)200,29 EUR
Bonuspunkte-5,00 EUR
Umsatzsteuer (19%)35,00 EUR
Umsatzsteuer (7%)2,50 EUR + EUR +
Umsatzsteuer (%) + EUR +
Gesamt:240,79 EUR + EUR +
@@ -37,7 +47,9 @@ th:src="@{/shop/articles/${item.article.id}/image.jpg}" class="s"/> - + + th:src="@{/shop/articles/{id}/image.jpg(id=${item.article.id})}" class="s"/> + @@ -114,7 +114,7 @@ Musterstraße 4 @@ -122,7 +122,7 @@ Musterstraße 4 From 95e52cc79dc4037806e823b8758d8bef0f67be3b Mon Sep 17 00:00:00 2001 From: Hannes Date: Sun, 10 May 2020 14:57:02 +0200 Subject: [PATCH 19/28] fix non-formatted and non-vatted price --- .../src/main/resources/templates/shop/articles/id.html | 6 +++--- prototype/src/main/resources/templates/shop/index.html | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/prototype/src/main/resources/templates/shop/articles/id.html b/prototype/src/main/resources/templates/shop/articles/id.html index 73de367..588b5be 100644 --- a/prototype/src/main/resources/templates/shop/articles/id.html +++ b/prototype/src/main/resources/templates/shop/articles/id.html @@ -23,7 +23,7 @@
-

+

EUR

@@ -32,7 +32,7 @@
-

+

EUR

EUR + EUR x @@ -45,11 +57,9 @@ @@ -64,11 +74,16 @@

Checkout

+ + +

Lieferadresse:

@@ -78,12 +93,10 @@ Musterstraße 42
-
- - -

Bestellübersicht

From f5a99700a076faf758ec1a5ca65a95cf4f0a0894 Mon Sep 17 00:00:00 2001 From: CodeSteak Date: Tue, 5 May 2020 23:34:17 +0200 Subject: [PATCH 08/28] Renice error handling --- .../controller/shop/ShopArticleController.java | 10 ++++++++-- .../controller/shop/ShopCheckoutController.java | 9 +++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopArticleController.java b/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopArticleController.java index 5670f49..3cb860f 100644 --- a/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopArticleController.java +++ b/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopArticleController.java @@ -8,6 +8,8 @@ import org.springframework.stereotype.Controller; import org.springframework.ui.Model; 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.List; @@ -59,7 +61,9 @@ public class ShopArticleController { } @PostMapping("/{id}") - public String shopArticlesByIdBuy(HttpSession session, + public String shopArticlesByIdBuy(HttpServletRequest request, + HttpServletResponse response, + HttpSession session, @RequestAttribute(value = "shoppingCart") ShoppingCart shoppingCart, @PathVariable("id") Long id, @RequestParam("quantity") Integer quantity, @@ -69,7 +73,9 @@ public class ShopArticleController { Optional
article = articleRepository.findById(id); if (!article.isPresent()) { - throw new RuntimeException("Article not found!"); + request.setAttribute("error", "Der Artikel wurde nicht gefunden."); + response.setStatus(HttpServletResponse.SC_NOT_FOUND); + return "error/404"; } if (setAmount != null && setAmount) { diff --git a/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopCheckoutController.java b/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopCheckoutController.java index 66ced97..ffdd9f3 100644 --- a/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopCheckoutController.java +++ b/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopCheckoutController.java @@ -20,6 +20,7 @@ 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; @@ -97,6 +98,8 @@ public class ShopCheckoutController { @PostMapping("/checkoutFinish") public String shopCheckoutFinish( + HttpServletRequest request, + HttpServletResponse response, @RequestAttribute(value = "user") User user, @RequestAttribute(value = "shoppingCart") ShoppingCart shoppingCart, @RequestParam("address") String address, @@ -105,6 +108,12 @@ public class ShopCheckoutController { @RequestParam("expected_total") Integer expectedPrice ) { + if (shoppingCart.getRevision() != cartRevision) { + request.setAttribute("error", "Der Warenkorb wurde zwischenzeitlich bearbeitet. Daher die 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(); From cdce22968d560aff156d32a97503ae8cf7eb25c4 Mon Sep 17 00:00:00 2001 From: CodeSteak Date: Wed, 6 May 2020 14:10:37 +0200 Subject: [PATCH 09/28] Implement proper querying of warehouse slot sums and booking accounts. --- .../ecommerce/components/SlotInitializer.java | 32 +++++++++++++++++++ .../shop/ShopCheckoutController.java | 4 +-- .../ecommerce/entities/warehouse/Slot.java | 17 ++++++++++ .../WarehouseBookingPositionSlotEntry.java | 6 +++- .../BookingAccountEntryRepository.java | 9 +++--- .../repos/warehouse/SlotRepository.java | 17 ++++++++++ ...useBookingPositionSlotEntryRepository.java | 6 ++-- 7 files changed, 80 insertions(+), 11 deletions(-) create mode 100644 prototype/src/main/java/org/hso/ecommerce/components/SlotInitializer.java create mode 100644 prototype/src/main/java/org/hso/ecommerce/entities/warehouse/Slot.java create mode 100644 prototype/src/main/java/org/hso/ecommerce/repos/warehouse/SlotRepository.java diff --git a/prototype/src/main/java/org/hso/ecommerce/components/SlotInitializer.java b/prototype/src/main/java/org/hso/ecommerce/components/SlotInitializer.java new file mode 100644 index 0000000..ce8c39b --- /dev/null +++ b/prototype/src/main/java/org/hso/ecommerce/components/SlotInitializer.java @@ -0,0 +1,32 @@ +package org.hso.ecommerce.components; + +import org.hso.ecommerce.entities.warehouse.Slot; +import org.hso.ecommerce.repos.warehouse.SlotRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import javax.annotation.PostConstruct; + +@Component +public class SlotInitializer { + + @Autowired + private final SlotRepository slotRepository = null; + + // TODO: use values form cfg. + private final int NUM_SLOTS = 50; + + @PostConstruct + public void init() { + for (int i = 1; i <= NUM_SLOTS; i++) { + if (!slotRepository.findBySlotNum(i).isPresent()) { + Slot slotAdded = new Slot(); + slotAdded.slotNum = i; + slotRepository.save(slotAdded); + + System.out.println("Added Slot " + i + " to DB"); + } + } + } + +} diff --git a/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopCheckoutController.java b/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopCheckoutController.java index ffdd9f3..ab4827f 100644 --- a/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopCheckoutController.java +++ b/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopCheckoutController.java @@ -122,14 +122,14 @@ public class ShopCheckoutController { expectedPrice, Address.fromString(address), PaymentMethod.fromCreditCarNumber(cardnumber), - bookingEntryRepository.getByUser(user).orElse(BookingAccountEntry.newUser(user)), + 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)); + action.addArticle(article, item.getAmount(), wbeseRepo.getByArticle(article.id)); } CreateOrderAction.Result result = action.finish(); diff --git a/prototype/src/main/java/org/hso/ecommerce/entities/warehouse/Slot.java b/prototype/src/main/java/org/hso/ecommerce/entities/warehouse/Slot.java new file mode 100644 index 0000000..6a56541 --- /dev/null +++ b/prototype/src/main/java/org/hso/ecommerce/entities/warehouse/Slot.java @@ -0,0 +1,17 @@ +package org.hso.ecommerce.entities.warehouse; + +import javax.persistence.*; +import javax.validation.constraints.NotNull; + +@Entity +@Table(name = "warehouse_slots") +public class Slot { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Basic + public long id; + + @NotNull + @Column(unique = true) + public int slotNum; +} diff --git a/prototype/src/main/java/org/hso/ecommerce/entities/warehouse/WarehouseBookingPositionSlotEntry.java b/prototype/src/main/java/org/hso/ecommerce/entities/warehouse/WarehouseBookingPositionSlotEntry.java index d9ca4c6..766398f 100644 --- a/prototype/src/main/java/org/hso/ecommerce/entities/warehouse/WarehouseBookingPositionSlotEntry.java +++ b/prototype/src/main/java/org/hso/ecommerce/entities/warehouse/WarehouseBookingPositionSlotEntry.java @@ -3,6 +3,7 @@ package org.hso.ecommerce.entities.warehouse; import org.hso.ecommerce.entities.shop.Article; import javax.persistence.*; +import javax.validation.constraints.NotNull; @Entity @Table(name = "warehouse_booking_position_entries") @@ -13,6 +14,7 @@ public class WarehouseBookingPositionSlotEntry { @Basic public long id; + @NotNull @ManyToOne public Article article; @@ -20,7 +22,9 @@ public class WarehouseBookingPositionSlotEntry { //public int newSumArticles; public int newSumSlot; - public int slot; + @NotNull + @ManyToOne + public Slot slot; public WarehouseBookingPositionSlotEntry copyAddAmount(int amount) { WarehouseBookingPositionSlotEntry e = new WarehouseBookingPositionSlotEntry(); diff --git a/prototype/src/main/java/org/hso/ecommerce/repos/booking/BookingAccountEntryRepository.java b/prototype/src/main/java/org/hso/ecommerce/repos/booking/BookingAccountEntryRepository.java index 657e34d..d842a3a 100644 --- a/prototype/src/main/java/org/hso/ecommerce/repos/booking/BookingAccountEntryRepository.java +++ b/prototype/src/main/java/org/hso/ecommerce/repos/booking/BookingAccountEntryRepository.java @@ -1,7 +1,6 @@ package org.hso.ecommerce.repos.booking; import org.hso.ecommerce.entities.booking.BookingAccountEntry; -import org.hso.ecommerce.entities.user.User; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.stereotype.Repository; @@ -11,13 +10,13 @@ import java.util.Optional; @Repository public interface BookingAccountEntryRepository extends JpaRepository { - @Query("SELECT e FROM BookingAccountEntry e WHERE e.userAccount = :user ORDER BY e.id DESC") - Optional getByUser(User user); + @Query(value = "SELECT * FROM booking_account_entries as e WHERE e.user_account_id = :user ORDER BY e.id DESC LIMIT 1", nativeQuery = true) + Optional getByUser(Long user); - @Query("SELECT e FROM BookingAccountEntry e WHERE e.isMainAccount = 1 ORDER BY e.id DESC") + @Query(value = "SELECT * FROM booking_account_entries as e WHERE e.is_main_account = 1 ORDER BY e.id DESC LIMIT 1", nativeQuery = true) Optional getByMain(); - @Query("SELECT e FROM BookingAccountEntry e WHERE e.isVATAccount = 1 ORDER BY e.id DESC") + @Query(value = "SELECT * FROM booking_account_entries as e WHERE e.isvataccount = 1 ORDER BY e.id DESC LIMIT 1", nativeQuery = true) Optional getByVat(); diff --git a/prototype/src/main/java/org/hso/ecommerce/repos/warehouse/SlotRepository.java b/prototype/src/main/java/org/hso/ecommerce/repos/warehouse/SlotRepository.java new file mode 100644 index 0000000..d0f00c0 --- /dev/null +++ b/prototype/src/main/java/org/hso/ecommerce/repos/warehouse/SlotRepository.java @@ -0,0 +1,17 @@ +package org.hso.ecommerce.repos.warehouse; + +import org.hso.ecommerce.entities.warehouse.Slot; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.stereotype.Repository; + +import java.util.Optional; + +@Repository +public interface SlotRepository extends JpaRepository { + + @Query("SELECT s FROM Slot s WHERE s.slotNum = :slotNum") + Optional findBySlotNum(int slotNum); + + +} diff --git a/prototype/src/main/java/org/hso/ecommerce/repos/warehouse/WarehouseBookingPositionSlotEntryRepository.java b/prototype/src/main/java/org/hso/ecommerce/repos/warehouse/WarehouseBookingPositionSlotEntryRepository.java index 839a017..962231a 100644 --- a/prototype/src/main/java/org/hso/ecommerce/repos/warehouse/WarehouseBookingPositionSlotEntryRepository.java +++ b/prototype/src/main/java/org/hso/ecommerce/repos/warehouse/WarehouseBookingPositionSlotEntryRepository.java @@ -1,6 +1,5 @@ package org.hso.ecommerce.repos.warehouse; -import org.hso.ecommerce.entities.shop.Article; import org.hso.ecommerce.entities.warehouse.WarehouseBookingPositionSlotEntry; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; @@ -12,7 +11,8 @@ import java.util.List; public interface WarehouseBookingPositionSlotEntryRepository extends JpaRepository { // TODO this is wrong. revisit. - @Query("SELECT e FROM WarehouseBookingPositionSlotEntry e WHERE e.article = :article ORDER BY e.id DESC") - List getByArticle(Article article); + // @Query("SELECT e FROM WarehouseBookingPositionSlotEntry e, Slot s WHERE e.slot = s AND e.article = :article GROUP BY e.slot.slotNum HAVING max(e.id)") + @Query(value = "Select e.id, e.article_id, e.new_sum_slot, e.slot_id from warehouse_booking_position_entries as e, warehouse_slots as s where e.slot_id = s.id AND e.article_id = :article GROUP BY s.slot_num HAVING max(e.id)", nativeQuery = true) + List getByArticle(long article); } From beb0131b60714f9c17c1fc4d9d969a0a67e71aba Mon Sep 17 00:00:00 2001 From: CodeSteak Date: Wed, 6 May 2020 17:00:28 +0200 Subject: [PATCH 10/28] Unify Style of error messages to match rest of ui. --- .../static/img/error_404_illustatus.svg | 377 +++++------------- .../static/img/error_generic_illustatus.svg | 352 ++++------------ .../main/resources/templates/error/404.html | 4 +- .../main/resources/templates/error/500.html | 4 +- 4 files changed, 177 insertions(+), 560 deletions(-) diff --git a/prototype/src/main/resources/static/img/error_404_illustatus.svg b/prototype/src/main/resources/static/img/error_404_illustatus.svg index 452b2d5..d58cd65 100644 --- a/prototype/src/main/resources/static/img/error_404_illustatus.svg +++ b/prototype/src/main/resources/static/img/error_404_illustatus.svg @@ -1,277 +1,100 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Oops, Page not found - - - - - \ No newline at end of file + + page not found + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/prototype/src/main/resources/static/img/error_generic_illustatus.svg b/prototype/src/main/resources/static/img/error_generic_illustatus.svg index f94a8d4..20143d7 100644 --- a/prototype/src/main/resources/static/img/error_generic_illustatus.svg +++ b/prototype/src/main/resources/static/img/error_generic_illustatus.svg @@ -1,277 +1,75 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Oops, something went wrong - - - - - \ No newline at end of file + + server down + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/prototype/src/main/resources/templates/error/404.html b/prototype/src/main/resources/templates/error/404.html index 699b4f5..a58016a 100644 --- a/prototype/src/main/resources/templates/error/404.html +++ b/prototype/src/main/resources/templates/error/404.html @@ -9,10 +9,8 @@
-

Error 404

+

Ein Fehler ist aufgetreten. Die gewünschte Ressource konnte nicht gefunden werden

-

Ein Fehler ist aufgetreten. Die gewünschte Ressource konnte nicht gefunden werden.

-
diff --git a/prototype/src/main/resources/templates/error/500.html b/prototype/src/main/resources/templates/error/500.html index f14f141..4f9747f 100644 --- a/prototype/src/main/resources/templates/error/500.html +++ b/prototype/src/main/resources/templates/error/500.html @@ -9,10 +9,8 @@
-

Error 500

+

Ein Fehler ist aufgetreten. Bitte versuche es später nocheinmal.

-

Ein Fehler ist aufgetreten. Bitte versuche es später nocheinmal.

-
From 4fd80bb3c76639c46640550498309da340afb447 Mon Sep 17 00:00:00 2001 From: Hannes Date: Thu, 7 May 2020 15:48:00 +0200 Subject: [PATCH 11/28] implement imageserving and first part of ArticleRepository --- .gitignore | 2 + prototype/.gitignore | 2 +- .../shop/ShopArticleController.java | 84 +++++++++++-------- .../controller/shop/ShopIndexController.java | 64 ++++---------- .../hso/ecommerce/entities/shop/Article.java | 1 + .../hso/ecommerce/entities/shop/Image.java | 5 +- .../repos/shop/ArticleRepository.java | 20 +++++ .../resources/templates/shop/articles/id.html | 4 +- .../main/resources/templates/shop/index.html | 8 +- 9 files changed, 98 insertions(+), 92 deletions(-) diff --git a/.gitignore b/.gitignore index 3b718f8..3912d2e 100644 --- a/.gitignore +++ b/.gitignore @@ -89,3 +89,5 @@ local.properties # SQLite prototype/*.db + +prototype/images diff --git a/prototype/.gitignore b/prototype/.gitignore index 59529a7..4fac9a9 100644 --- a/prototype/.gitignore +++ b/prototype/.gitignore @@ -1,4 +1,4 @@ -./test.db +./e-commerce.db ./build ./gradle ./out diff --git a/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopArticleController.java b/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopArticleController.java index 3cb860f..a6159d9 100644 --- a/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopArticleController.java +++ b/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopArticleController.java @@ -1,9 +1,11 @@ package org.hso.ecommerce.controller.shop; +import org.apache.tomcat.util.http.fileupload.IOUtils; import org.hso.ecommerce.entities.shop.Article; import org.hso.ecommerce.entities.shop.ShoppingCart; import org.hso.ecommerce.repos.shop.ArticleRepository; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.MediaType; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.*; @@ -11,7 +13,10 @@ 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.io.ByteArrayInputStream; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; import java.util.List; import java.util.Optional; @@ -23,40 +28,35 @@ public class ShopArticleController { private final ArticleRepository articleRepository = null; @GetMapping("/{id}") - public String shopArticlesById(Model model, @PathVariable("id") Integer Id) { + public String shopArticlesById(Model model, + @PathVariable("id") Long id, + HttpServletRequest request, + HttpServletResponse response + ) { - //TODO: Get Article by Id instead of this dummy shit - Article d1 = new Article(); - d1.description = "this is dummy1"; - d1.title = "dummy1"; - d1.shopPricePerUnitNetCent = 1500; - d1.id = 1234; - model.addAttribute("article", d1); + Article article = articleRepository.findArticleById(id); + + + if(article == null) { + request.setAttribute("error", "Der Artikel wurde nicht gefunden."); + response.setStatus(HttpServletResponse.SC_NOT_FOUND); + return "error/404"; + } + + model.addAttribute("article", article); //TODO: Check if in Stock - if(false){ + if (false) { model.addAttribute("inStock", true); - }else{ + } else { model.addAttribute("inStock", false); } - //TODO: Get 2 Commercialised Articles - List
commercialArticles = new ArrayList
(); - Article d2 = new Article(); - d2.description = "this is dummy2"; - d2.title = "dummy2"; - d2.shopPricePerUnitNetCent = 2000; - d2.id = 2345; - Article d3 = new Article(); - d3.description = "this is dummy3"; - d3.title = "dummy3"; - d3.shopPricePerUnitNetCent = 2500; - d3.id = 3456; - commercialArticles.add(d2); - commercialArticles.add(d3); + List
commercialArticles = articleRepository.getCommercialisedArticles("2"); model.addAttribute("commercialArticles", commercialArticles); + return "shop/articles/id"; } @@ -71,17 +71,19 @@ public class ShopArticleController { @RequestParam("fastcheckout") Boolean fastcheckout ) { - Optional
article = articleRepository.findById(id); - if (!article.isPresent()) { - request.setAttribute("error", "Der Artikel wurde nicht gefunden."); - response.setStatus(HttpServletResponse.SC_NOT_FOUND); - return "error/404"; - } + + Article article = articleRepository.findArticleById(id); + +// if (!article.isPresent()) { +// request.setAttribute("error", "Der Artikel wurde nicht gefunden."); +// response.setStatus(HttpServletResponse.SC_NOT_FOUND); +// return "error/404"; +// } if (setAmount != null && setAmount) { - shoppingCart.setArticleCount(article.get(), quantity); + shoppingCart.setArticleCount(article, quantity); } else { - shoppingCart.addArticle(article.get(), quantity); + shoppingCart.addArticle(article, quantity); } if (!fastcheckout) { @@ -90,4 +92,20 @@ public class ShopArticleController { return "redirect:/shop/checkout"; } } + + @GetMapping("/{id}/image.jpg") + public void getImageAsByteArray(HttpServletRequest request, + HttpServletResponse response, + @PathVariable("id") Long id + ) throws IOException { + + Article article = articleRepository.findArticleById(id); + + InputStream in = new FileInputStream(article.image.path); + response.setContentType(MediaType.IMAGE_JPEG_VALUE); + IOUtils.copy(in, response.getOutputStream()); + } + + } + diff --git a/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopIndexController.java b/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopIndexController.java index 0be1a50..69dce5d 100644 --- a/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopIndexController.java +++ b/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopIndexController.java @@ -1,6 +1,8 @@ package org.hso.ecommerce.controller.shop; import org.hso.ecommerce.entities.shop.Article; +import org.hso.ecommerce.repos.shop.ArticleRepository; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; @@ -8,13 +10,15 @@ import org.springframework.web.bind.annotation.RequestMapping; import javax.servlet.http.HttpSession; import javax.swing.*; -import java.awt.*; -import java.util.ArrayList; +import java.util.List; @Controller @RequestMapping("/") public class ShopIndexController { + @Autowired + private final ArticleRepository articleRepository = null; + @GetMapping("/") public String home() { return "redirect:/shop/"; @@ -23,8 +27,7 @@ public class ShopIndexController { @GetMapping("/shop/") public String shop(Model model, HttpSession session) { - //TODO: get commercialised Articles - ArrayList
commercialArticles = getArticles(); + List
commercialArticles = articleRepository.getCommercialisedArticles("4"); model.addAttribute("commercialArticles", commercialArticles); //check if logged in @@ -33,20 +36,19 @@ public class ShopIndexController { if (session != null && session.getAttribute("id") != null) { long userId = (long) session.getAttribute("id"); isLoggedIn = true; - if (false) { - hasOrders = true; //TODO: Find out whether user has orders! + } + + if (isLoggedIn) { + List
suggestedArticles = articleRepository.getLastOrderedArticles("4"); + if(suggestedArticles.size() > 0) { + model.addAttribute("suggestedArticles", suggestedArticles); + hasOrders = true; } } + model.addAttribute("isLoggedIn", isLoggedIn); model.addAttribute("hasOrders", hasOrders); - - if (hasOrders) { - //TODO: get up to last 4 Orders - ArrayList
suggestedArticles = getArticles(); - model.addAttribute("suggestedArticles", suggestedArticles); - } - return "shop/index"; } @@ -65,40 +67,4 @@ public class ShopIndexController { return "privacy"; } - - public ArrayList
getArticles() { - ArrayList
dummyArticles = new ArrayList
(); - - Article d1 = new Article(); - d1.description = "this is dummy1"; - d1.title = "dummy1"; - d1.shopPricePerUnitNetCent = 1500; - d1.id = 1234; - dummyArticles.add(d1); - - Article d2 = new Article(); - d2.description = "this is dummy2"; - d2.title = "dummy2"; - d2.shopPricePerUnitNetCent = 2000; - d2.id = 2345; - dummyArticles.add(d2); - - Article d3 = new Article(); - d3.description = "this is dummy3"; - d3.title = "dummy3"; - d3.shopPricePerUnitNetCent = 2500; - d3.id = 3456; - dummyArticles.add(d3); - - Article d4 = new Article(); - d4.description = "this is dummy4"; - d4.title = "dummy4"; - d4.shopPricePerUnitNetCent = 3000; - d4.id = 4567; - dummyArticles.add(d4); - - return dummyArticles; - } - - } diff --git a/prototype/src/main/java/org/hso/ecommerce/entities/shop/Article.java b/prototype/src/main/java/org/hso/ecommerce/entities/shop/Article.java index 2e066cd..a26cb39 100644 --- a/prototype/src/main/java/org/hso/ecommerce/entities/shop/Article.java +++ b/prototype/src/main/java/org/hso/ecommerce/entities/shop/Article.java @@ -32,6 +32,7 @@ public class Article { public String description; @OneToOne(optional = true) + @Basic(fetch = FetchType.LAZY) public Image image; @ManyToMany diff --git a/prototype/src/main/java/org/hso/ecommerce/entities/shop/Image.java b/prototype/src/main/java/org/hso/ecommerce/entities/shop/Image.java index 33eebdb..d27d415 100644 --- a/prototype/src/main/java/org/hso/ecommerce/entities/shop/Image.java +++ b/prototype/src/main/java/org/hso/ecommerce/entities/shop/Image.java @@ -11,7 +11,6 @@ public class Image { @Basic public long id; - @Lob - @Column(name = "data", columnDefinition = "BLOB", nullable = false) - private byte[] data; + public String path; } + diff --git a/prototype/src/main/java/org/hso/ecommerce/repos/shop/ArticleRepository.java b/prototype/src/main/java/org/hso/ecommerce/repos/shop/ArticleRepository.java index 0ac4bd2..42ef5ee 100644 --- a/prototype/src/main/java/org/hso/ecommerce/repos/shop/ArticleRepository.java +++ b/prototype/src/main/java/org/hso/ecommerce/repos/shop/ArticleRepository.java @@ -1,11 +1,31 @@ package org.hso.ecommerce.repos.shop; import org.hso.ecommerce.entities.shop.Article; +import org.hso.ecommerce.entities.user.User; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; +import java.util.List; +import java.util.Optional; + @Repository public interface ArticleRepository extends JpaRepository { + @Query(nativeQuery = true, value = "Select * FROM articles where articles.id = :articleId") + Article findArticleById(@Param("articleId") long articleId); + + + //TODO: getCommercialisedArticles(int quantity) + @Query("SELECT c FROM User c WHERE c.email = :quantity") + List
getCommercialisedArticles(@Param("quantity") String quantity); + + + //TODO: getLastOrderedArticles(int quantity) + @Query("SELECT c FROM User c WHERE c.email = :quantity") + List
getLastOrderedArticles(@Param("quantity") String quantity); + + } diff --git a/prototype/src/main/resources/templates/shop/articles/id.html b/prototype/src/main/resources/templates/shop/articles/id.html index 46b7c93..c82aedb 100644 --- a/prototype/src/main/resources/templates/shop/articles/id.html +++ b/prototype/src/main/resources/templates/shop/articles/id.html @@ -27,7 +27,7 @@

- +
@@ -56,7 +56,7 @@

Weitere Schnäppchen

-
+

Jetzt Shoppen und Empfehlungen erhalten!

-
+
- +

From c097e58bf36b0dc5ddce228353612abd9e915bbf Mon Sep 17 00:00:00 2001 From: Hannes Date: Fri, 8 May 2020 09:58:29 +0200 Subject: [PATCH 12/28] change Databasename and add Advertisementflag --- prototype/.gitignore | 2 +- .../ecommerce/controller/shop/ShopArticleController.java | 4 +--- .../ecommerce/controller/shop/ShopIndexController.java | 3 +-- .../org/hso/ecommerce/entities/supplier/ArticleOffer.java | 2 ++ .../org/hso/ecommerce/repos/shop/ArticleRepository.java | 8 +++----- prototype/src/main/resources/application.properties | 2 +- prototype/src/main/resources/templates/shop/checkout.html | 3 ++- 7 files changed, 11 insertions(+), 13 deletions(-) diff --git a/prototype/.gitignore b/prototype/.gitignore index 4fac9a9..52b353d 100644 --- a/prototype/.gitignore +++ b/prototype/.gitignore @@ -1,4 +1,4 @@ -./e-commerce.db +e-commerce.db ./build ./gradle ./out diff --git a/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopArticleController.java b/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopArticleController.java index a6159d9..6d8cea9 100644 --- a/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopArticleController.java +++ b/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopArticleController.java @@ -13,12 +13,10 @@ import org.springframework.web.bind.annotation.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; -import java.io.ByteArrayInputStream; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.List; -import java.util.Optional; @Controller @RequestMapping("/shop/articles") @@ -53,7 +51,7 @@ public class ShopArticleController { model.addAttribute("inStock", false); } - List

commercialArticles = articleRepository.getCommercialisedArticles("2"); + List
commercialArticles = articleRepository.getAdvertisedArticles(); model.addAttribute("commercialArticles", commercialArticles); diff --git a/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopIndexController.java b/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopIndexController.java index 69dce5d..73c3241 100644 --- a/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopIndexController.java +++ b/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopIndexController.java @@ -9,7 +9,6 @@ import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import javax.servlet.http.HttpSession; -import javax.swing.*; import java.util.List; @Controller @@ -27,7 +26,7 @@ public class ShopIndexController { @GetMapping("/shop/") public String shop(Model model, HttpSession session) { - List
commercialArticles = articleRepository.getCommercialisedArticles("4"); + List
commercialArticles = articleRepository.getAdvertisedArticles(); model.addAttribute("commercialArticles", commercialArticles); //check if logged in diff --git a/prototype/src/main/java/org/hso/ecommerce/entities/supplier/ArticleOffer.java b/prototype/src/main/java/org/hso/ecommerce/entities/supplier/ArticleOffer.java index 005b0b9..ce02d13 100644 --- a/prototype/src/main/java/org/hso/ecommerce/entities/supplier/ArticleOffer.java +++ b/prototype/src/main/java/org/hso/ecommerce/entities/supplier/ArticleOffer.java @@ -19,4 +19,6 @@ public class ArticleOffer { public String articleNumber; public int vatPercent; + + public boolean should_be_advertised; } diff --git a/prototype/src/main/java/org/hso/ecommerce/repos/shop/ArticleRepository.java b/prototype/src/main/java/org/hso/ecommerce/repos/shop/ArticleRepository.java index 42ef5ee..a22f191 100644 --- a/prototype/src/main/java/org/hso/ecommerce/repos/shop/ArticleRepository.java +++ b/prototype/src/main/java/org/hso/ecommerce/repos/shop/ArticleRepository.java @@ -13,16 +13,14 @@ import java.util.Optional; @Repository public interface ArticleRepository extends JpaRepository { - @Query(nativeQuery = true, value = "Select * FROM articles where articles.id = :articleId") + @Query("Select a FROM Article a where a.id = :articleId") Article findArticleById(@Param("articleId") long articleId); - //TODO: getCommercialisedArticles(int quantity) - @Query("SELECT c FROM User c WHERE c.email = :quantity") - List
getCommercialisedArticles(@Param("quantity") String quantity); + @Query("SELECT a from Article a join a.related ao where ao.should_be_advertised = true") + List
getAdvertisedArticles(); - //TODO: getLastOrderedArticles(int quantity) @Query("SELECT c FROM User c WHERE c.email = :quantity") List
getLastOrderedArticles(@Param("quantity") String quantity); diff --git a/prototype/src/main/resources/application.properties b/prototype/src/main/resources/application.properties index b62e80f..18ec88c 100644 --- a/prototype/src/main/resources/application.properties +++ b/prototype/src/main/resources/application.properties @@ -3,7 +3,7 @@ spring.resources.cache.cachecontrol.maxAge=P0D # LOGGING logging.level.org.springframework.web=WARN # DATABASE -spring.datasource.url=jdbc:sqlite:./test.db +spring.datasource.url=jdbc:sqlite:./e-commerce.db spring.datasource.driverClassName=org.sqlite.JDBC spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.SQLiteDialect spring.jpa.hibernate.ddl-auto=update diff --git a/prototype/src/main/resources/templates/shop/checkout.html b/prototype/src/main/resources/templates/shop/checkout.html index cf02b5c..9962649 100644 --- a/prototype/src/main/resources/templates/shop/checkout.html +++ b/prototype/src/main/resources/templates/shop/checkout.html @@ -44,7 +44,8 @@

Date: Fri, 8 May 2020 10:37:42 +0200 Subject: [PATCH 13/28] Advertised Articles now shown correctly --- .../action/shop/GetRandomArticlesAction.java | 20 +++++++++++++++++++ .../shop/ShopArticleController.java | 6 ++++-- .../controller/shop/ShopIndexController.java | 6 ++++-- .../resources/templates/shop/articles/id.html | 4 ++-- .../main/resources/templates/shop/index.html | 2 +- 5 files changed, 31 insertions(+), 7 deletions(-) create mode 100644 prototype/src/main/java/org/hso/ecommerce/action/shop/GetRandomArticlesAction.java diff --git a/prototype/src/main/java/org/hso/ecommerce/action/shop/GetRandomArticlesAction.java b/prototype/src/main/java/org/hso/ecommerce/action/shop/GetRandomArticlesAction.java new file mode 100644 index 0000000..2c6fd55 --- /dev/null +++ b/prototype/src/main/java/org/hso/ecommerce/action/shop/GetRandomArticlesAction.java @@ -0,0 +1,20 @@ +package org.hso.ecommerce.action.shop; + +import org.hso.ecommerce.entities.shop.Article; + +import java.util.ArrayList; +import java.util.List; + +public class GetRandomArticlesAction { + + public static List
getRandomArticles(int quantity, List
advertisedArticles) { + List
randomisedArticles = new ArrayList
(); + for (int i = 0; i < quantity; i++) { + int index = (int) (Math.random() * advertisedArticles.size()); + randomisedArticles.add(advertisedArticles.remove(index)); + if(advertisedArticles.size() == 0) + break; + } + return randomisedArticles; + } +} diff --git a/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopArticleController.java b/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopArticleController.java index 6d8cea9..eb13de9 100644 --- a/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopArticleController.java +++ b/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopArticleController.java @@ -1,6 +1,7 @@ package org.hso.ecommerce.controller.shop; import org.apache.tomcat.util.http.fileupload.IOUtils; +import org.hso.ecommerce.action.shop.GetRandomArticlesAction; import org.hso.ecommerce.entities.shop.Article; import org.hso.ecommerce.entities.shop.ShoppingCart; import org.hso.ecommerce.repos.shop.ArticleRepository; @@ -16,6 +17,7 @@ import javax.servlet.http.HttpSession; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; +import java.util.ArrayList; import java.util.List; @Controller @@ -36,7 +38,7 @@ public class ShopArticleController { Article article = articleRepository.findArticleById(id); - if(article == null) { + if (article == null) { request.setAttribute("error", "Der Artikel wurde nicht gefunden."); response.setStatus(HttpServletResponse.SC_NOT_FOUND); return "error/404"; @@ -51,7 +53,7 @@ public class ShopArticleController { model.addAttribute("inStock", false); } - List
commercialArticles = articleRepository.getAdvertisedArticles(); + List
commercialArticles = GetRandomArticlesAction.getRandomArticles(4, articleRepository.getAdvertisedArticles()); model.addAttribute("commercialArticles", commercialArticles); diff --git a/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopIndexController.java b/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopIndexController.java index 73c3241..8844c8b 100644 --- a/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopIndexController.java +++ b/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopIndexController.java @@ -1,5 +1,6 @@ package org.hso.ecommerce.controller.shop; +import org.hso.ecommerce.action.shop.GetRandomArticlesAction; import org.hso.ecommerce.entities.shop.Article; import org.hso.ecommerce.repos.shop.ArticleRepository; import org.springframework.beans.factory.annotation.Autowired; @@ -9,6 +10,7 @@ import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import javax.servlet.http.HttpSession; +import java.util.ArrayList; import java.util.List; @Controller @@ -26,7 +28,7 @@ public class ShopIndexController { @GetMapping("/shop/") public String shop(Model model, HttpSession session) { - List
commercialArticles = articleRepository.getAdvertisedArticles(); + List
commercialArticles = GetRandomArticlesAction.getRandomArticles(8, articleRepository.getAdvertisedArticles()); model.addAttribute("commercialArticles", commercialArticles); //check if logged in @@ -39,7 +41,7 @@ public class ShopIndexController { if (isLoggedIn) { List
suggestedArticles = articleRepository.getLastOrderedArticles("4"); - if(suggestedArticles.size() > 0) { + if (suggestedArticles.size() > 0) { model.addAttribute("suggestedArticles", suggestedArticles); hasOrders = true; } diff --git a/prototype/src/main/resources/templates/shop/articles/id.html b/prototype/src/main/resources/templates/shop/articles/id.html index c82aedb..73de367 100644 --- a/prototype/src/main/resources/templates/shop/articles/id.html +++ b/prototype/src/main/resources/templates/shop/articles/id.html @@ -27,7 +27,7 @@

- +
@@ -56,7 +56,7 @@

Weitere Schnäppchen

- +

diff --git a/prototype/src/main/resources/templates/shop/index.html b/prototype/src/main/resources/templates/shop/index.html index bb6e4cd..f38b012 100644 --- a/prototype/src/main/resources/templates/shop/index.html +++ b/prototype/src/main/resources/templates/shop/index.html @@ -21,7 +21,7 @@
- +

From 1bd267a26dd55173090605998a289074838f1784 Mon Sep 17 00:00:00 2001 From: Hannes Date: Fri, 8 May 2020 11:44:30 +0200 Subject: [PATCH 14/28] implement personalized suggestions --- .../controller/shop/ShopArticleController.java | 10 +++++----- .../ecommerce/controller/shop/ShopIndexController.java | 6 ++++-- .../hso/ecommerce/repos/shop/ArticleRepository.java | 8 ++++---- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopArticleController.java b/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopArticleController.java index eb13de9..3b906d0 100644 --- a/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopArticleController.java +++ b/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopArticleController.java @@ -74,11 +74,11 @@ public class ShopArticleController { Article article = articleRepository.findArticleById(id); -// if (!article.isPresent()) { -// request.setAttribute("error", "Der Artikel wurde nicht gefunden."); -// response.setStatus(HttpServletResponse.SC_NOT_FOUND); -// return "error/404"; -// } + if (article == null) { + request.setAttribute("error", "Der Artikel wurde nicht gefunden."); + response.setStatus(HttpServletResponse.SC_NOT_FOUND); + return "error/404"; + } if (setAmount != null && setAmount) { shoppingCart.setArticleCount(article, quantity); diff --git a/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopIndexController.java b/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopIndexController.java index 8844c8b..9fa8c37 100644 --- a/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopIndexController.java +++ b/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopIndexController.java @@ -2,6 +2,7 @@ package org.hso.ecommerce.controller.shop; import org.hso.ecommerce.action.shop.GetRandomArticlesAction; import org.hso.ecommerce.entities.shop.Article; +import org.hso.ecommerce.entities.user.User; import org.hso.ecommerce.repos.shop.ArticleRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; @@ -31,7 +32,7 @@ public class ShopIndexController { List

commercialArticles = GetRandomArticlesAction.getRandomArticles(8, articleRepository.getAdvertisedArticles()); model.addAttribute("commercialArticles", commercialArticles); - //check if logged in + boolean isLoggedIn = false; boolean hasOrders = false; if (session != null && session.getAttribute("id") != null) { @@ -40,7 +41,8 @@ public class ShopIndexController { } if (isLoggedIn) { - List
suggestedArticles = articleRepository.getLastOrderedArticles("4"); + List
suggestedArticles = articleRepository.getLastOrderedArticles(); + suggestedArticles = suggestedArticles.size() > 3 ? suggestedArticles.subList(0,3) : suggestedArticles; //only latest 4 articles if (suggestedArticles.size() > 0) { model.addAttribute("suggestedArticles", suggestedArticles); hasOrders = true; diff --git a/prototype/src/main/java/org/hso/ecommerce/repos/shop/ArticleRepository.java b/prototype/src/main/java/org/hso/ecommerce/repos/shop/ArticleRepository.java index a22f191..933959f 100644 --- a/prototype/src/main/java/org/hso/ecommerce/repos/shop/ArticleRepository.java +++ b/prototype/src/main/java/org/hso/ecommerce/repos/shop/ArticleRepository.java @@ -13,16 +13,16 @@ import java.util.Optional; @Repository public interface ArticleRepository extends JpaRepository { - @Query("Select a FROM Article a where a.id = :articleId") + @Query("SELECT a FROM Article a WHERE a.id = :articleId") Article findArticleById(@Param("articleId") long articleId); - @Query("SELECT a from Article a join a.related ao where ao.should_be_advertised = true") + @Query("SELECT a FROM Article a JOIN a.related ao WHERE ao.should_be_advertised = true") List
getAdvertisedArticles(); - @Query("SELECT c FROM User c WHERE c.email = :quantity") - List
getLastOrderedArticles(@Param("quantity") String quantity); + @Query("SELECT a FROM CustomerOrderPosition cop JOIN cop.order co JOIN co.customer c JOIN cop.article a ORDER BY co.id DESC") + List
getLastOrderedArticles(); } From c0ce1e23c3ac3f5e5cd6a79c8998f988d53c3487 Mon Sep 17 00:00:00 2001 From: Hannes Date: Fri, 8 May 2020 13:01:29 +0200 Subject: [PATCH 15/28] fix better quantities for UI --- .../action/shop/GetRandomArticlesAction.java | 5 ++--- .../controller/shop/ShopArticleController.java | 12 +++++++++--- .../controller/shop/ShopIndexController.java | 5 ++--- .../hso/ecommerce/repos/shop/ArticleRepository.java | 2 +- 4 files changed, 14 insertions(+), 10 deletions(-) diff --git a/prototype/src/main/java/org/hso/ecommerce/action/shop/GetRandomArticlesAction.java b/prototype/src/main/java/org/hso/ecommerce/action/shop/GetRandomArticlesAction.java index 2c6fd55..c299b92 100644 --- a/prototype/src/main/java/org/hso/ecommerce/action/shop/GetRandomArticlesAction.java +++ b/prototype/src/main/java/org/hso/ecommerce/action/shop/GetRandomArticlesAction.java @@ -9,11 +9,10 @@ public class GetRandomArticlesAction { public static List
getRandomArticles(int quantity, List
advertisedArticles) { List
randomisedArticles = new ArrayList
(); - for (int i = 0; i < quantity; i++) { + int loopcount = quantity > advertisedArticles.size() ? advertisedArticles.size() : quantity; + for (int i = 0; i < loopcount; i++) { int index = (int) (Math.random() * advertisedArticles.size()); randomisedArticles.add(advertisedArticles.remove(index)); - if(advertisedArticles.size() == 0) - break; } return randomisedArticles; } diff --git a/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopArticleController.java b/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopArticleController.java index 3b906d0..03da5b7 100644 --- a/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopArticleController.java +++ b/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopArticleController.java @@ -4,7 +4,9 @@ import org.apache.tomcat.util.http.fileupload.IOUtils; import org.hso.ecommerce.action.shop.GetRandomArticlesAction; import org.hso.ecommerce.entities.shop.Article; import org.hso.ecommerce.entities.shop.ShoppingCart; +import org.hso.ecommerce.entities.warehouse.WarehouseBookingPositionSlotEntry; import org.hso.ecommerce.repos.shop.ArticleRepository; +import org.hso.ecommerce.repos.warehouse.WarehouseBookingPositionSlotEntryRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; import org.springframework.stereotype.Controller; @@ -27,6 +29,9 @@ public class ShopArticleController { @Autowired private final ArticleRepository articleRepository = null; + @Autowired + private final WarehouseBookingPositionSlotEntryRepository warehouseBookingPositionSlotEntryRepository = null; + @GetMapping("/{id}") public String shopArticlesById(Model model, @PathVariable("id") Long id, @@ -46,14 +51,15 @@ public class ShopArticleController { model.addAttribute("article", article); - //TODO: Check if in Stock - if (false) { + + //if (warehouseBookingPositionSlotEntryRepository.getByArticle(id).get(0).newSumSlot > 0) { //TODO: use this as soon as warehouse works + if (true) { model.addAttribute("inStock", true); } else { model.addAttribute("inStock", false); } - List
commercialArticles = GetRandomArticlesAction.getRandomArticles(4, articleRepository.getAdvertisedArticles()); + List
commercialArticles = GetRandomArticlesAction.getRandomArticles(3, articleRepository.getAdvertisedArticles()); model.addAttribute("commercialArticles", commercialArticles); diff --git a/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopIndexController.java b/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopIndexController.java index 9fa8c37..e660eb0 100644 --- a/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopIndexController.java +++ b/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopIndexController.java @@ -32,7 +32,6 @@ public class ShopIndexController { List
commercialArticles = GetRandomArticlesAction.getRandomArticles(8, articleRepository.getAdvertisedArticles()); model.addAttribute("commercialArticles", commercialArticles); - boolean isLoggedIn = false; boolean hasOrders = false; if (session != null && session.getAttribute("id") != null) { @@ -41,8 +40,8 @@ public class ShopIndexController { } if (isLoggedIn) { - List
suggestedArticles = articleRepository.getLastOrderedArticles(); - suggestedArticles = suggestedArticles.size() > 3 ? suggestedArticles.subList(0,3) : suggestedArticles; //only latest 4 articles + List
suggestedArticles = articleRepository.getOrderedArticles(); + suggestedArticles = suggestedArticles.size() > 3 ? suggestedArticles.subList(0,4) : suggestedArticles; //only latest 4 articles if (suggestedArticles.size() > 0) { model.addAttribute("suggestedArticles", suggestedArticles); hasOrders = true; diff --git a/prototype/src/main/java/org/hso/ecommerce/repos/shop/ArticleRepository.java b/prototype/src/main/java/org/hso/ecommerce/repos/shop/ArticleRepository.java index 933959f..2a88b7e 100644 --- a/prototype/src/main/java/org/hso/ecommerce/repos/shop/ArticleRepository.java +++ b/prototype/src/main/java/org/hso/ecommerce/repos/shop/ArticleRepository.java @@ -22,7 +22,7 @@ public interface ArticleRepository extends JpaRepository { @Query("SELECT a FROM CustomerOrderPosition cop JOIN cop.order co JOIN co.customer c JOIN cop.article a ORDER BY co.id DESC") - List
getLastOrderedArticles(); + List
getOrderedArticles(); } From 731f4761fab17d3e8df39c43a99f6285e7b4b4b0 Mon Sep 17 00:00:00 2001 From: CodeSteak Date: Sun, 10 May 2020 14:29:08 +0200 Subject: [PATCH 16/28] Show error if articles are not avail during checkout. --- .../action/shop/CreateOrderAction.java | 22 +++++++++++++++++-- .../shop/ShopCheckoutController.java | 20 ++++++++++++----- 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/prototype/src/main/java/org/hso/ecommerce/action/shop/CreateOrderAction.java b/prototype/src/main/java/org/hso/ecommerce/action/shop/CreateOrderAction.java index ed1066c..8b35be8 100644 --- a/prototype/src/main/java/org/hso/ecommerce/action/shop/CreateOrderAction.java +++ b/prototype/src/main/java/org/hso/ecommerce/action/shop/CreateOrderAction.java @@ -68,7 +68,8 @@ public class CreateOrderAction { totalVatCent += article.getVat() * quantity; } - public Result finish() { + + public Result finish() throws ArticleNotInStockException { CustomerOrder order = createOrder(); CustomerPayment payment = createPayment(); @@ -86,7 +87,7 @@ public class CreateOrderAction { ); } - private WarehouseBooking createWarehouseBooking(CustomerOrder order) { + private WarehouseBooking createWarehouseBooking(CustomerOrder order) throws ArticleNotInStockException { WarehouseBooking booking = new WarehouseBooking(); booking.created = new Timestamp(new Date().getTime()); booking.reason = new BookingReason(order); @@ -111,6 +112,10 @@ public class CreateOrderAction { break; } } + + if (needed > 0) { + throw new ArticleNotInStockException(item.article); + } } return booking; @@ -174,4 +179,17 @@ public class CreateOrderAction { this.quantity = quantity; } } + + public static class ArticleNotInStockException extends Exception { + private Article article; + + public ArticleNotInStockException(Article article) { + super("The quantity of article '" + article.title + "' is not in stock."); + this.article = article; + } + + public Article getArticle() { + return article; + } + } } diff --git a/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopCheckoutController.java b/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopCheckoutController.java index ab4827f..c2c1c3a 100644 --- a/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopCheckoutController.java +++ b/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopCheckoutController.java @@ -98,6 +98,7 @@ public class ShopCheckoutController { @PostMapping("/checkoutFinish") public String shopCheckoutFinish( + HttpSession session, HttpServletRequest request, HttpServletResponse response, @RequestAttribute(value = "user") User user, @@ -132,15 +133,22 @@ public class ShopCheckoutController { action.addArticle(article, item.getAmount(), wbeseRepo.getByArticle(article.id)); } - CreateOrderAction.Result result = action.finish(); + CreateOrderAction.Result result = null; + try { + result = action.finish(); + EnableTrackingAction.addTrackingInfo(result.customerOrder); - EnableTrackingAction.addTrackingInfo(result.customerOrder); + customerOderRepository.save(result.customerOrder); + bookingRepository.saveAll(result.bookings); + warehouseBookingRepository.save(result.warehouseBooking); - customerOderRepository.save(result.customerOrder); - bookingRepository.saveAll(result.bookings); - warehouseBookingRepository.save(result.warehouseBooking); + 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); + } - shoppingCart.clear(); return "shop/checkoutFinish"; } From d1301f69887829139044a059721b58797c7cf4e6 Mon Sep 17 00:00:00 2001 From: CodeSteak Date: Sun, 10 May 2020 14:30:00 +0200 Subject: [PATCH 17/28] Fix naming-convension-error in ArticleOffer --- .../org/hso/ecommerce/entities/supplier/ArticleOffer.java | 2 +- .../hso/ecommerce/entities/warehouse/WarehouseBooking.java | 1 + .../java/org/hso/ecommerce/repos/shop/ArticleRepository.java | 4 +--- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/prototype/src/main/java/org/hso/ecommerce/entities/supplier/ArticleOffer.java b/prototype/src/main/java/org/hso/ecommerce/entities/supplier/ArticleOffer.java index ce02d13..ae86659 100644 --- a/prototype/src/main/java/org/hso/ecommerce/entities/supplier/ArticleOffer.java +++ b/prototype/src/main/java/org/hso/ecommerce/entities/supplier/ArticleOffer.java @@ -20,5 +20,5 @@ public class ArticleOffer { public int vatPercent; - public boolean should_be_advertised; + public boolean shouldBeAdvertised; } diff --git a/prototype/src/main/java/org/hso/ecommerce/entities/warehouse/WarehouseBooking.java b/prototype/src/main/java/org/hso/ecommerce/entities/warehouse/WarehouseBooking.java index cf60734..08eaa40 100644 --- a/prototype/src/main/java/org/hso/ecommerce/entities/warehouse/WarehouseBooking.java +++ b/prototype/src/main/java/org/hso/ecommerce/entities/warehouse/WarehouseBooking.java @@ -27,6 +27,7 @@ public class WarehouseBooking { ) public List positions = new ArrayList<>(); + // TODO FIX ME @OneToOne(optional = false, cascade = CascadeType.ALL) public BookingReason reason; } diff --git a/prototype/src/main/java/org/hso/ecommerce/repos/shop/ArticleRepository.java b/prototype/src/main/java/org/hso/ecommerce/repos/shop/ArticleRepository.java index 2a88b7e..90b6d11 100644 --- a/prototype/src/main/java/org/hso/ecommerce/repos/shop/ArticleRepository.java +++ b/prototype/src/main/java/org/hso/ecommerce/repos/shop/ArticleRepository.java @@ -1,14 +1,12 @@ package org.hso.ecommerce.repos.shop; import org.hso.ecommerce.entities.shop.Article; -import org.hso.ecommerce.entities.user.User; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; import java.util.List; -import java.util.Optional; @Repository public interface ArticleRepository extends JpaRepository { @@ -17,7 +15,7 @@ public interface ArticleRepository extends JpaRepository { Article findArticleById(@Param("articleId") long articleId); - @Query("SELECT a FROM Article a JOIN a.related ao WHERE ao.should_be_advertised = true") + @Query("SELECT a FROM Article a JOIN a.related ao WHERE ao.shouldBeAdvertised = true") List
getAdvertisedArticles(); From d4d1426438de504f09201ac75c914df086e9f57f Mon Sep 17 00:00:00 2001 From: CodeSteak Date: Sun, 10 May 2020 14:34:20 +0200 Subject: [PATCH 18/28] Fix decimals in checkout page --- prototype/src/main/resources/templates/shop/checkout.html | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/prototype/src/main/resources/templates/shop/checkout.html b/prototype/src/main/resources/templates/shop/checkout.html index 9962649..786885f 100644 --- a/prototype/src/main/resources/templates/shop/checkout.html +++ b/prototype/src/main/resources/templates/shop/checkout.html @@ -49,7 +49,7 @@

+ th:text="${#numbers.formatDecimal(item.article.getPriceGross() * 0.01, 1, 'POINT', 2, 'COMMA')}"> EUR x @@ -106,7 +106,7 @@ Musterstraße 4
Artikel (Netto) + th:text="${#numbers.formatDecimal(checkoutTotals.net * 0.01, 1, 'POINT', 2, 'COMMA')}"> EUR
Umsatzsteuer (%) + th:text="${#numbers.formatDecimal(item.getValue() * 0.01, 1, 'POINT', 2, 'COMMA')}"> EUR
Gesamt: + th:text="${#numbers.formatDecimal(checkoutTotals.total * 0.01, 1, 'POINT', 2, 'COMMA')}"> EUR