diff --git a/.gitignore b/.gitignore index 3912d2e..c52eb76 100644 --- a/.gitignore +++ b/.gitignore @@ -91,3 +91,5 @@ local.properties prototype/*.db prototype/images +prototype/data + diff --git a/prototype/build.gradle b/prototype/build.gradle index c7defd9..c8e14cb 100644 --- a/prototype/build.gradle +++ b/prototype/build.gradle @@ -3,7 +3,7 @@ buildscript { mavenCentral() } dependencies { - classpath("org.springframework.boot:spring-boot-gradle-plugin:2.2.2.RELEASE") + classpath("org.springframework.boot:spring-boot-gradle-plugin:2.2.7.RELEASE") } } @@ -27,7 +27,7 @@ dependencies { // implementation 'org.springframework.session:spring-session-jdbc' implementation 'com.github.gwenn:sqlite-dialect:0.1.0' implementation 'org.springframework.boot:spring-boot-devtools' - implementation 'org.xerial:sqlite-jdbc:3.28.0' + implementation 'org.xerial:sqlite-jdbc:3.31.1' testCompile("org.springframework.boot:spring-boot-starter-test") } diff --git a/prototype/gradle/wrapper/gradle-wrapper.jar b/prototype/gradle/wrapper/gradle-wrapper.jar index f6b961f..5c2d1cf 100644 Binary files a/prototype/gradle/wrapper/gradle-wrapper.jar and b/prototype/gradle/wrapper/gradle-wrapper.jar differ diff --git a/prototype/gradle/wrapper/gradle-wrapper.properties b/prototype/gradle/wrapper/gradle-wrapper.properties index 7c4388a..4c5803d 100644 --- a/prototype/gradle/wrapper/gradle-wrapper.properties +++ b/prototype/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.4-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/prototype/gradlew b/prototype/gradlew old mode 100755 new mode 100644 index cccdd3d..83f2acf --- a/prototype/gradlew +++ b/prototype/gradlew @@ -1,5 +1,21 @@ #!/usr/bin/env sh +# +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + ############################################################################## ## ## Gradle start up script for UN*X @@ -28,7 +44,7 @@ APP_NAME="Gradle" APP_BASE_NAME=`basename "$0"` # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD="maximum" @@ -109,8 +125,8 @@ if $darwin; then GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" fi -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then APP_HOME=`cygpath --path --mixed "$APP_HOME"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` JAVACMD=`cygpath --unix "$JAVACMD"` diff --git a/prototype/gradlew.bat b/prototype/gradlew.bat index e95643d..24467a1 100644 --- a/prototype/gradlew.bat +++ b/prototype/gradlew.bat @@ -1,3 +1,19 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + @if "%DEBUG%" == "" @echo off @rem ########################################################################## @rem @@ -14,7 +30,7 @@ set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome diff --git a/prototype/scripts/addarticles.sql b/prototype/scripts/addarticles.sql index f7e5f5b..b60497d 100644 --- a/prototype/scripts/addarticles.sql +++ b/prototype/scripts/addarticles.sql @@ -1,5 +1,5 @@ -INSERT INTO article_offers ("manufacturer", "article_number", "vat_percent", "should_be_advertised") -VALUES ("McDonalds", "1", 7, 1); +INSERT INTO article_offers ("manufacturer", "article_number", "price_per_unit_net", "title", "vat_percent", "should_be_advertised") +VALUES ("McDonalds", "1", 4242, "McPizza", 7, 1); INSERT INTO articles ("related_id", "shop_price_per_unit_net_cent", "warehouse_units_per_slot", "should_reorder", "reorder_max_price", "title", "description", "image_id") VALUES (1, 19.99, 10, 1, 15, "Huge Hamburger", "This huge Hamburger is awesome!", NULL); 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 3adf74e..bb0b5d6 100644 --- a/prototype/src/main/java/org/hso/ecommerce/app/RequestController.java +++ b/prototype/src/main/java/org/hso/ecommerce/app/RequestController.java @@ -52,6 +52,12 @@ public class RequestController { return "login"; } + if (!user.get().isActive) { + request.setAttribute("error", "User ist deaktiviert."); + response.setStatus(HttpServletResponse.SC_EXPECTATION_FAILED); + return "login"; + } + session.setAttribute("userId", user.get().getId()); if (gto != null && gto.startsWith("/")) { @@ -69,53 +75,11 @@ public class RequestController { return "redirect:/"; } - @GetMapping("/register") - public String register() { - return "register"; - } - - @PostMapping("/register") - public String registerPost( - @RequestParam("username") String username, - @RequestParam("password") String password, - @RequestParam("password2") String password2, - @RequestParam("type") String type - ) { - - return "redirect:/"; - } - - @GetMapping("/shop/search") - public String shopSearch() { - return "shop/search"; - } - @GetMapping("/intern/") public String intern() { return "intern/index"; } - - @GetMapping("/intern/listedArticles/") - public String internListedArticles() { - return "intern/listedArticles/index"; - } - - @GetMapping("/intern/listedArticles/{id}") - public String internListedArticlesId() { - return "intern/listedArticles/id"; - } - - - @GetMapping("/intern/articles/") - public String internArticles() { - return "intern/articles/index"; - } - - @GetMapping("/intern/articles/{id}") - public String internArticlesId() { - return "intern/articles/id"; - } - + @GetMapping("/intern/customers/") public String internCustomers() { return "intern/customers/index"; @@ -155,6 +119,15 @@ public class RequestController { public String internSupplierOrdersId() { return "intern/supplierOrders/id"; } + + /* + + @GetMapping("/intern/suppliersOffers") + public String internSuppliersOffers() { + return "intern/offeredArticles/index"; + } + */ + @GetMapping("/intern/accounting/") public String accounting() { diff --git a/prototype/src/main/java/org/hso/ecommerce/components/LoginIntercepter.java b/prototype/src/main/java/org/hso/ecommerce/components/LoginIntercepter.java index 8e1fc1d..e537867 100644 --- a/prototype/src/main/java/org/hso/ecommerce/components/LoginIntercepter.java +++ b/prototype/src/main/java/org/hso/ecommerce/components/LoginIntercepter.java @@ -24,6 +24,7 @@ public class LoginIntercepter implements HandlerInterceptor { HttpSession session = request.getSession(); Object userId = session.getAttribute("userId"); + Optional user = null; if (request.getRequestURI().startsWith("/user/")) { System.out.println("USER"); @@ -43,10 +44,24 @@ public class LoginIntercepter implements HandlerInterceptor { response.sendRedirect("/login"); return false; } + + user = userRepository.findById((Long) userId); + + if(user.isPresent() && !user.get().isEmployee) + { + session.setAttribute("afterLogin", request.getRequestURI()); + response.sendRedirect("/"); + return false; + } + } + + if (!request.getRequestURI().startsWith("/login")) { + session.removeAttribute("afterLogin"); } if (userId != null) { - Optional user = userRepository.findById((Long) userId); + if (user == null) + user = userRepository.findById((Long) userId); user.ifPresent(value -> request.setAttribute("user", value)); } diff --git a/prototype/src/main/java/org/hso/ecommerce/controller/RegisterController.java b/prototype/src/main/java/org/hso/ecommerce/controller/RegisterController.java new file mode 100644 index 0000000..a53e084 --- /dev/null +++ b/prototype/src/main/java/org/hso/ecommerce/controller/RegisterController.java @@ -0,0 +1,74 @@ +package org.hso.ecommerce.controller; + +import org.hso.ecommerce.entities.shop.Address; +import org.hso.ecommerce.entities.user.User; +import org.hso.ecommerce.repos.user.UserRepository; +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.RequestParam; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.util.Optional; + +@Controller +public class RegisterController { + + @Autowired + private final UserRepository userRepository = null; + + @PostMapping("/register") + public String registerPost( + HttpServletRequest request, + HttpServletResponse response, + @RequestParam("username") String username, + @RequestParam("password") String password, + @RequestParam("password2") String password2, + @RequestParam("salutation") String salutation, + @RequestParam("name") String name, + @RequestParam("address") String address, + @RequestParam("type") String type, + @RequestParam("ad") String ad + ) + { + Optional user = userRepository.findByEmail(username); + if (user.isPresent()) { + request.setAttribute("error", "Email Adresse existiert bereits!"); + response.setStatus(HttpServletResponse.SC_EXPECTATION_FAILED); + return "register"; + } + + if (!password.equals(password2)){ + request.setAttribute("error", "Passwörter sind nicht gleich"); + response.setStatus(HttpServletResponse.SC_BAD_REQUEST); + return "register"; + } + + //set values for new user + User newUser = new User(); + newUser.email = username; + newUser.setPassword(password); + newUser.email = username; + newUser.isEmployee = false; + //TODO for salutation, type, ad are no attributes/fields in the class/database. Add when they are there. + + newUser.isActive = true; + newUser.created = new java.sql.Timestamp(System.currentTimeMillis()); + + Address newAddress = new Address(); + newAddress.name = name; + newAddress.addressString = address; + newUser.defaultDeliveryAddress = newAddress; + + userRepository.save(newUser); // save newUser + + return "redirect:/login"; + } + + @GetMapping("/register") + public String register() { + return "register"; + } +} diff --git a/prototype/src/main/java/org/hso/ecommerce/controller/intern/InternArticleController.java b/prototype/src/main/java/org/hso/ecommerce/controller/intern/InternArticleController.java index d078f54..1d54302 100644 --- a/prototype/src/main/java/org/hso/ecommerce/controller/intern/InternArticleController.java +++ b/prototype/src/main/java/org/hso/ecommerce/controller/intern/InternArticleController.java @@ -1,8 +1,364 @@ package org.hso.ecommerce.controller.intern; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import javax.imageio.ImageIO; + +import org.hso.ecommerce.entities.shop.Article; +import org.hso.ecommerce.entities.shop.Category; +import org.hso.ecommerce.entities.shop.Image; +import org.hso.ecommerce.entities.supplier.ArticleOffer; +import org.hso.ecommerce.repos.shop.ArticleRepository; +import org.hso.ecommerce.repos.shop.CategoryRepository; +import org.hso.ecommerce.repos.shop.ImageRepository; +import org.hso.ecommerce.repos.shop.OffersRepository; +import org.hso.ecommerce.repos.warehouse.WarehouseBookingPositionSlotEntryRepository; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.util.DigestUtils; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.servlet.view.RedirectView; @Controller -//@RequestMapping("...") +@RequestMapping("intern/articles") public class InternArticleController { + @Autowired + private final ArticleRepository articleRepository = null; + + @Autowired + private final WarehouseBookingPositionSlotEntryRepository warehouseEntryRepository = null; + + @Autowired + private final CategoryRepository categoryRepository = null; + + @Autowired + private final OffersRepository offersRepository = null; + + @Autowired + private final ImageRepository imageRepository = null; + + @GetMapping("/") + public String internListedArticles(Model model) { + + List totals = new ArrayList(); + + for (Article article : articleRepository.findAll()) { + UImodelArticles tmp = new UImodelArticles(); + tmp.addListedArticle(article, warehouseEntryRepository.getArticleStock(article.id).orElse(0)); + totals.add(tmp); + } + + model.addAttribute("ListedArticles", totals); + return "intern/listedArticles/index"; + } + + @GetMapping("/{id}") + public String internListedArticlesId(Model model, @PathVariable String id) { + + int articleid = Integer.parseInt(id); + + UImodelArticle total = new UImodelArticle(); + + total.addArticle(articleRepository.findArticleById(articleid), + warehouseEntryRepository.getArticleStock(articleid).orElse(0)); + + model.addAttribute("ArticleID", total); + + return "intern/listedArticles/id"; + } + + @PostMapping("/{id}/saveChanges") + public RedirectView saveChanges(@PathVariable(required = true) int id, + @RequestParam(value = "title", required = true) String title, + @RequestParam(value = "description", required = true) String description, + @RequestParam(value = "units-per-slot", required = true) String warehouseUnitsPerSlot, + @RequestParam(value = "price_netto", required = true) String pricenetto, + @RequestParam(value = "reorderMaxPrice", required = true) String reorderMaxPrice, + @RequestParam(value = "autobuy", required = true) Boolean shouldReorder, + @RequestParam(value = "categories", required = true) String categories, + @RequestParam(value = "img", required = true) MultipartFile imgFile) { + + Article tmpArticle = articleRepository.findArticleById(id); // get the old article + + String[] separatedCategories = categories.split("\n"); + + tmpArticle.categories.clear(); + + // loop through all categories strings and create a new category if a new one; + // also adds the categorys to the article + for (String category : separatedCategories) { + tmpArticle.categories.add(categoryRepository.findCategoryByName(category.trim()) + .orElseGet(() -> new Category(category.trim()))); + } + + tmpArticle.shouldReorder = shouldReorder; + tmpArticle.reorderMaxPrice = (int) (Float.parseFloat(reorderMaxPrice) * 100); + tmpArticle.shopPricePerUnitNetCent = (int) (Float.parseFloat(pricenetto) * 100); + tmpArticle.warehouseUnitsPerSlot = Integer.parseInt(warehouseUnitsPerSlot); + tmpArticle.title = title; + updateImage(tmpArticle, imgFile); + tmpArticle.description = description; + + articleRepository.save(tmpArticle); // save updated article + return new RedirectView("../"); // return to overview page + + } + + @PostMapping("/addArticle/{id}") + public RedirectView addArticle(@PathVariable(required = true) String id) { + // article is not already listed, create new one + int offeredArticleID = Integer.parseInt(id); + + Article tmpArticle = new Article(); + + ArticleOffer offeredArticle = offersRepository.findOfferedArticleById(offeredArticleID); + + // set default values + tmpArticle.description = ""; + tmpArticle.reorderMaxPrice = 0; + tmpArticle.shopPricePerUnitNetCent = offeredArticle.pricePerUnitNet; + tmpArticle.shouldReorder = false; + tmpArticle.title = offeredArticle.title; + tmpArticle.warehouseUnitsPerSlot = 1; + setDefaultImage(tmpArticle); + tmpArticle.related = offeredArticle; + articleRepository.save(tmpArticle); // save new article + + // return to edit article page + return new RedirectView("../" + articleRepository.findArticleIDByRelatedID(offeredArticleID).get()); + } + + private void setDefaultImage(Article article) { + String defaultImagePath = "./data/img/no_product_img.jpg"; // path + name of default img + Optional imageID = imageRepository.findImageIDByPath(defaultImagePath); // get default img + + if (imageID.isPresent()) { + // default img is in DB + article.image = imageRepository.findImageById(imageID.get()); // set default img to new article + } else { + // default img is not in DB + File tmpFile = new File(defaultImagePath); + // test if default img file exits + if (!tmpFile.exists()) { + // fallback if the file not exists + // create new file + BufferedImage bufferedImage = new BufferedImage(422, 428, BufferedImage.TYPE_INT_RGB); + try { + ImageIO.write(bufferedImage, "jpg", new File(defaultImagePath)); // save new file on disk + } catch (IOException e) { + e.printStackTrace(); + } + } + Image defaultImage = new Image(); + defaultImage.path = defaultImagePath; // set new file to default img + imageRepository.save(defaultImage); // save default img + article.image = defaultImage; // set default img to new article + } + } + + private void updateImage(Article article, MultipartFile imgFile) { + // check if a file is present + if (imgFile.getSize() > 0) { + try { + // get file name based on MD5 hash + String fileName = DigestUtils.md5DigestAsHex(imgFile.getBytes()) + ".jpg"; + // check if img is already in system + Optional imageID = imageRepository.findImageIDByPath("./data/img/" + fileName); + if (imageID.isPresent()) { + article.image = imageRepository.findImageById(imageID.get()); // add existing img to article + } else { + // write new img file to disk + Files.newOutputStream(Paths.get("./data/img/", fileName)).write(imgFile.getBytes()); + // create new img + Image newImage = new Image(); + newImage.path = "./data/img/" + fileName; // set new file to new img + imageRepository.save(newImage); // save new img + article.image = newImage; // set new img to article + } + } catch (Exception e) { + setDefaultImage(article); // if upload failed, reset to default img + } + } + } + + public static class UImodelArticles { + + public String imgPath; + + public String title; + + public String price; + + public String price_netto; + + public String categorie; + + public int stock; + + public long offer_id; + + public long id; + + void addListedArticle(Article article, int stock) { + this.imgPath = article.image.path; + this.title = article.title; + this.price_netto = String.format("%.2f", ((float) article.shopPricePerUnitNetCent / 100)); + this.price = String.format("%.2f", ((float) article.getPriceGross() / 100)); + + StringBuilder result = new StringBuilder(); + + for (Category temp : article.categories) { + result.append(temp.name + " "); + } + this.categorie = result.toString(); + + this.stock = stock; + this.offer_id = article.related.id; + this.id = article.id; + } + } + + public static class UImodelArticle { + + public String imgPath; + public String title; + public String price; + public String price_netto; + public String reorderMaxPrice; + public String categorie; + public int stock; + public long offer_id; + public long id; + public boolean shouldReorder; + public String warehouseUnitsPerSlot; + public String description; + + public String getImgPath() { + return imgPath; + } + + public void setImgPath(String imgPath) { + this.imgPath = imgPath; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getPrice() { + return price; + } + + public void setPrice(String price) { + this.price = price; + } + + public String getPrice_netto() { + return price_netto; + } + + public void setPrice_netto(String price_netto) { + this.price_netto = price_netto; + } + + public String getReorderMaxPrice() { + return reorderMaxPrice; + } + + public void setReorderMaxPrice(String reorderMaxPrice) { + this.reorderMaxPrice = reorderMaxPrice; + } + + public String getCategorie() { + return categorie; + } + + public void setCategorie(String categorie) { + this.categorie = categorie; + } + + public int getStock() { + return stock; + } + + public void setStock(int stock) { + this.stock = stock; + } + + public long getOffer_id() { + return offer_id; + } + + public void setOffer_id(long offer_id) { + this.offer_id = offer_id; + } + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public boolean isShouldReorder() { + return shouldReorder; + } + + public void setShouldReorder(boolean shouldReorder) { + this.shouldReorder = shouldReorder; + } + + public String getWarehouseUnitsPerSlot() { + return warehouseUnitsPerSlot; + } + + public void setWarehouseUnitsPerSlot(String warehouseUnitsPerSlot) { + this.warehouseUnitsPerSlot = warehouseUnitsPerSlot; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + void addArticle(Article article, int stock) { + this.imgPath = article.image.path; + this.title = article.title; + this.price_netto = String.format("%.2f", ((float) article.shopPricePerUnitNetCent / 100)); + this.price = String.format("%.2f", ((float) article.getPriceGross() / 100)); + + StringBuilder result = new StringBuilder(); + + for (Category temp : article.categories) { + result.append(temp.name); + result.append("\n"); + } + this.categorie = result.toString(); + + this.stock = stock; + this.offer_id = article.related.id; + this.id = article.id; + this.reorderMaxPrice = String.format("%.2f", ((float) article.reorderMaxPrice / 100)); + this.shouldReorder = article.shouldReorder; + this.warehouseUnitsPerSlot = String.valueOf(article.warehouseUnitsPerSlot); + this.description = article.description; + } + } + } diff --git a/prototype/src/main/java/org/hso/ecommerce/controller/intern/suppliers/SupplierOfferController.java b/prototype/src/main/java/org/hso/ecommerce/controller/intern/suppliers/SupplierOfferController.java index ec6dfbf..3ef21bf 100644 --- a/prototype/src/main/java/org/hso/ecommerce/controller/intern/suppliers/SupplierOfferController.java +++ b/prototype/src/main/java/org/hso/ecommerce/controller/intern/suppliers/SupplierOfferController.java @@ -1,8 +1,156 @@ package org.hso.ecommerce.controller.intern.suppliers; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +import org.hso.ecommerce.entities.supplier.ArticleOffer; +import org.hso.ecommerce.repos.shop.ArticleRepository; +import org.hso.ecommerce.repos.shop.OffersRepository; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; @Controller -//@RequestMapping("...") +@RequestMapping("/intern/") public class SupplierOfferController { + + @Autowired + private final OffersRepository offersRepository = null; + + @Autowired + private final ArticleRepository articleRepository = null; + + @GetMapping("supplierOffers") + public String internListedArticles(Model model) { + + List totals = new ArrayList(); + + for (ArticleOffer article : offersRepository.findAll()) { + UImodelOfferedArticle tmp = new UImodelOfferedArticle(); + tmp.addData(article, "supplierName01", 4884, articleRepository.findArticleIDByRelatedID(article.id)); //TODO display supplier name with link + totals.add(tmp); + } + + model.addAttribute("OfferedArticles", totals); + return "intern/offeredArticles/index"; + } + + public class UImodelOfferedArticle { + + long offer_id; + String title; + String manufacturer; + String articlenumber; + String supplierName; + int supplierId; + String price; + String ads; + int listedArticleId; + boolean offerIsListed; //true --> offered article is listed + + public long getOffer_id() { + return offer_id; + } + + public void setOffer_id(long offer_id) { + this.offer_id = offer_id; + } + + public boolean isOfferIsListed() { + return offerIsListed; + } + + public void setOfferIsListed(boolean offerIsListed) { + this.offerIsListed = offerIsListed; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getManufacturer() { + return manufacturer; + } + + public void setManufacturer(String manufacturer) { + this.manufacturer = manufacturer; + } + + public String getArticlenumber() { + return articlenumber; + } + + public void setArticlenumber(String articlenumber) { + this.articlenumber = articlenumber; + } + + public String getSupplierName() { + return supplierName; + } + + public void setSupplierName(String supplierName) { + this.supplierName = supplierName; + } + + public int getSupplierId() { + return supplierId; + } + + public void setSupplierId(int supplierId) { + this.supplierId = supplierId; + } + + public String getPrice() { + return price; + } + + public void setPrice(String price) { + this.price = price; + } + + public String getAds() { + return ads; + } + + public void setAds(String ads) { + this.ads = ads; + } + + public int getListedArticleId() { + return listedArticleId; + } + + public void setListedArticleId(int listedArticleId) { + this.listedArticleId = listedArticleId; + } + + public void addData(ArticleOffer article, String supplierName, int supplierId, + Optional listedArticleId) { + + this.offer_id = article.id; + this.title = article.title; + this.manufacturer = article.manufacturer; + this.articlenumber = article.articleNumber; + this.supplierName = supplierName; + this.supplierId = supplierId; + this.price = String.format("%.2f", ((float) article.pricePerUnitNet / 100)); + this.ads = (article.shouldBeAdvertised) ? "Ja" : "Nein"; + + if (listedArticleId.isPresent()) { + // this offer is listed --> show link + this.listedArticleId = listedArticleId.get(); + offerIsListed = true; + } else { + // this offer is not listed + offerIsListed = false; + } + } + } } 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 2fc0aa2..235669c 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 @@ -5,6 +5,7 @@ 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; +import org.hso.ecommerce.repos.shop.CategoryRepository; import org.hso.ecommerce.repos.warehouse.WarehouseBookingPositionSlotEntryRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; @@ -30,12 +31,17 @@ public class ShopArticleController { @Autowired private final WarehouseBookingPositionSlotEntryRepository warehouseBookingPositionSlotEntryRepository = null; + @Autowired + private final CategoryRepository categoryRepository = null; + @GetMapping("/{id}") public String shopArticlesById(Model model, @PathVariable("id") Long id, HttpServletRequest request, HttpServletResponse response ) { + model.addAttribute("categories", categoryRepository.getCategories()); //for sidebar + Article article = articleRepository.findArticleById(id); if (article == null) { @@ -45,14 +51,13 @@ public class ShopArticleController { } model.addAttribute("article", article); - //if (warehouseBookingPositionSlotEntryRepository.getByArticle(id).get(0).newSumSlot > 0) { //TODO: use this as soon as warehouse works - if (true) { + if (warehouseBookingPositionSlotEntryRepository.getByArticle(id).get(0).newSumSlot > 0) { //check if in Stock model.addAttribute("inStock", true); } else { model.addAttribute("inStock", false); } - List
commercialArticles = GetRandomArticlesAction.getRandomArticles(3, articleRepository.getAdvertisedArticles()); + List
commercialArticles = GetRandomArticlesAction.getRandomArticles(3, articleRepository.getAdvertisedArticles()); //get 3 advertised Articles model.addAttribute("commercialArticles", commercialArticles); return "shop/articles/id"; @@ -99,5 +104,4 @@ public class ShopArticleController { response.setContentType(MediaType.IMAGE_JPEG_VALUE); IOUtils.copy(in, response.getOutputStream()); } -} - +} \ No newline at end of file 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 15b6067..71ecf70 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 @@ -3,6 +3,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.repos.shop.ArticleRepository; +import org.hso.ecommerce.repos.warehouse.WarehouseBookingPositionSlotEntryRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; @@ -19,6 +20,9 @@ public class ShopIndexController { @Autowired private final ArticleRepository articleRepository = null; + @Autowired + private final WarehouseBookingPositionSlotEntryRepository warehouseBookingPositionSlotEntryRepository = null; + @GetMapping("/") public String home() { return "redirect:/shop/"; @@ -27,18 +31,18 @@ public class ShopIndexController { @GetMapping("/shop/") public String shop(Model model, HttpSession session) { - List
commercialArticles = GetRandomArticlesAction.getRandomArticles(8, articleRepository.getAdvertisedArticles()); + List
commercialArticles = GetRandomArticlesAction.getRandomArticles(8, articleRepository.getAdvertisedArticles()); //get random advertised Articles model.addAttribute("commercialArticles", commercialArticles); boolean isLoggedIn = false; boolean hasOrders = false; - if (session != null && session.getAttribute("userId") != null) { + if (session != null && session.getAttribute("userId") != null) { //check if logged in long userId = (long) session.getAttribute("userId"); isLoggedIn = true; List
suggestedArticles = articleRepository.getOrderedArticles(userId); - suggestedArticles = suggestedArticles.size() > 3 ? suggestedArticles.subList(0, 4) : suggestedArticles; //only latest 4 articles + suggestedArticles = suggestedArticles.size() > 3 ? suggestedArticles.subList(0, 4) : suggestedArticles; //only latest 4 ordered articles if (suggestedArticles.size() > 0) { model.addAttribute("suggestedArticles", suggestedArticles); hasOrders = true; @@ -65,5 +69,4 @@ public class ShopIndexController { public String privacy() { return "privacy"; } - } diff --git a/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopSearchController.java b/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopSearchController.java index 05a795f..1d14c61 100644 --- a/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopSearchController.java +++ b/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopSearchController.java @@ -1,8 +1,48 @@ package org.hso.ecommerce.controller.shop; +import org.hso.ecommerce.entities.shop.Article; +import org.hso.ecommerce.repos.shop.ArticleRepository; +import org.hso.ecommerce.repos.shop.CategoryRepository; +import org.springframework.beans.factory.annotation.Autowired; 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 java.util.List; @Controller -//@RequestMapping("...") +@RequestMapping("/shop/search") public class ShopSearchController { -} + + @Autowired + private final ArticleRepository articleRepository = null; + + @Autowired + private final CategoryRepository categoryRepository = null; + + @GetMapping("") + public String searchArticles(@RequestParam(required = false, value = "term") String term, + @RequestParam(required = false, value = "category") String category, + Model model, + HttpServletRequest request, + HttpServletResponse response + ) { + model.addAttribute("categories", categoryRepository.getCategories()); //for sidebar + + if (term != null) { //if search by Term + List
articles = articleRepository.getArticlesByTerm(term); //search by Term + model.addAttribute("articles", articles); + } else if (category != null) { //if search by Category + List
articles = articleRepository.getArticlesByCategory(category); //search by Category + model.addAttribute("articles", articles); + } else { + request.setAttribute("error", "Es wurden keine Suchparameter angegeben."); + response.setStatus(HttpServletResponse.SC_NOT_FOUND); + return "error/404"; + } + + return "/shop/search"; + } +} \ No newline at end of file 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 4f81062..af0a9c0 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 @@ -1,11 +1,10 @@ package org.hso.ecommerce.entities.booking; import javax.persistence.Embeddable; -import javax.validation.constraints.NotNull; @Embeddable public class PaymentMethod { - @NotNull + public String creditCardNumber; public static PaymentMethod fromCreditCarNumber(String cardnumber) { 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 a26cb39..355b5f9 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 @@ -35,7 +35,7 @@ public class Article { @Basic(fetch = FetchType.LAZY) public Image image; - @ManyToMany + @ManyToMany(cascade = CascadeType.ALL) @JoinTable(name = "article_categories_bindings") public Set categories = new HashSet<>(); @@ -46,4 +46,4 @@ public class Article { public int getPriceGross() { return shopPricePerUnitNetCent + getVat(); } -} +} \ No newline at end of file diff --git a/prototype/src/main/java/org/hso/ecommerce/entities/shop/Category.java b/prototype/src/main/java/org/hso/ecommerce/entities/shop/Category.java index 13b0b54..d552869 100644 --- a/prototype/src/main/java/org/hso/ecommerce/entities/shop/Category.java +++ b/prototype/src/main/java/org/hso/ecommerce/entities/shop/Category.java @@ -1,7 +1,5 @@ package org.hso.ecommerce.entities.shop; -import org.hso.ecommerce.entities.shop.Article; - import javax.persistence.*; import javax.validation.constraints.NotNull; import java.util.HashSet; @@ -22,4 +20,15 @@ public class Category { @ManyToMany(mappedBy = "categories") public Set
articles = new HashSet<>(); + + + public Category() { + + } + + + public Category (String name) { + this.name = name; + } + } 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 ae86659..405fb4a 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 @@ -14,6 +14,12 @@ public class ArticleOffer { @NotNull public String manufacturer; + + @NotNull + public String title; + + @NotNull + public int pricePerUnitNet; @NotNull public String articleNumber; @@ -21,4 +27,6 @@ public class ArticleOffer { public int vatPercent; public boolean shouldBeAdvertised; + + } 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 0b108f1..0340f59 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 @@ -7,21 +7,32 @@ 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("SELECT a FROM Article a WHERE a.id = :articleId") - Article findArticleById(@Param("articleId") long articleId); + @Query("SELECT a FROM Article a WHERE a.id = :articleId") + Article findArticleById(@Param("articleId") long articleId); + @Query("SELECT a FROM Article a") + List
findAll(); - @Query("SELECT a FROM Article a JOIN a.related ao WHERE ao.shouldBeAdvertised = true") + @Query(value = "Select a.* from articles as a, article_offers as ao, warehouse_booking_position_entries as wbpe where a.related_id = ao.id and wbpe.article_id = a.id and ao.should_be_advertised = true group by wbpe.slot_id having max(wbpe.id) and wbpe.new_sum_slot != 0", nativeQuery = true) List
getAdvertisedArticles(); + @Query("SELECT a FROM CustomerOrderPosition cop JOIN cop.order co JOIN co.customer c JOIN cop.article a ORDER BY co.id DESC") + List
getOrderedArticles(); @Query("SELECT a FROM CustomerOrderPosition cop JOIN cop.order co JOIN co.customer c JOIN cop.article a WHERE c.id = :customerId ORDER BY co.id DESC") List
getOrderedArticles(long customerId); + @Query(value = "SELECT a.id FROM articles a WHERE a.related_id = :relatedId", nativeQuery = true) + Optional findArticleIDByRelatedID(@Param("relatedId") long relatedId); + + @Query(value = "Select a.* from articles as a, warehouse_booking_position_entries as wbpe where wbpe.article_id = a.id and a.title LIKE %:term% group by wbpe.slot_id having max(wbpe.id) and wbpe.new_sum_slot != 0", nativeQuery = true) + List
getArticlesByTerm(String term); -} - + @Query(value = "Select a.* from articles as a, categories as c, article_categories_bindings as acb, warehouse_booking_position_entries as wbpe where wbpe.article_id = a.id and acb.articles_id = a.id and acb.categories_id = c.id and c.name = :category group by wbpe.slot_id having max(wbpe.id) and wbpe.new_sum_slot != 0", nativeQuery = true) + List
getArticlesByCategory(String category); +} \ No newline at end of file diff --git a/prototype/src/main/java/org/hso/ecommerce/repos/shop/CategoryRepository.java b/prototype/src/main/java/org/hso/ecommerce/repos/shop/CategoryRepository.java new file mode 100644 index 0000000..4f4133a --- /dev/null +++ b/prototype/src/main/java/org/hso/ecommerce/repos/shop/CategoryRepository.java @@ -0,0 +1,20 @@ +package org.hso.ecommerce.repos.shop; + +import org.hso.ecommerce.entities.shop.Category; +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 CategoryRepository extends JpaRepository { + + @Query("SELECT a FROM Category a WHERE a.name = :name") + Optional findCategoryByName(@Param("name") String name); + + @Query("SELECT c FROM Category c") + List getCategories(); +} \ No newline at end of file diff --git a/prototype/src/main/java/org/hso/ecommerce/repos/shop/ImageRepository.java b/prototype/src/main/java/org/hso/ecommerce/repos/shop/ImageRepository.java new file mode 100644 index 0000000..d0f3997 --- /dev/null +++ b/prototype/src/main/java/org/hso/ecommerce/repos/shop/ImageRepository.java @@ -0,0 +1,20 @@ +package org.hso.ecommerce.repos.shop; + +import org.hso.ecommerce.entities.shop.Image; +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.Optional; + +@Repository +public interface ImageRepository extends JpaRepository { + + @Query("SELECT i.id FROM Image i WHERE i.path = :path") + Optional findImageIDByPath(@Param("path") String path); + + @Query("SELECT i FROM Image i WHERE i.id = :imageId") + Image findImageById(@Param("imageId") long imageId); + +} diff --git a/prototype/src/main/java/org/hso/ecommerce/repos/shop/OffersRepository.java b/prototype/src/main/java/org/hso/ecommerce/repos/shop/OffersRepository.java new file mode 100644 index 0000000..20a3f90 --- /dev/null +++ b/prototype/src/main/java/org/hso/ecommerce/repos/shop/OffersRepository.java @@ -0,0 +1,20 @@ +package org.hso.ecommerce.repos.shop; + +import java.util.List; + +import org.hso.ecommerce.entities.supplier.ArticleOffer; +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; + +@Repository +public interface OffersRepository extends JpaRepository { + + @Query("SELECT a FROM ArticleOffer a") + List findAll(); + + @Query("SELECT a FROM ArticleOffer a WHERE a.id = :offeredarticleId") + ArticleOffer findOfferedArticleById(@Param("offeredarticleId") long offeredarticleId); + +} 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 c3eab4b..cb9902e 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 @@ -6,12 +6,17 @@ import org.springframework.data.jpa.repository.Query; import org.springframework.stereotype.Repository; import java.util.List; +import java.util.Optional; @Repository public interface WarehouseBookingPositionSlotEntryRepository extends JpaRepository { @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); - + + + @Query(value = "SELECT SUM(w.new_sum_slot) FROM warehouse_booking_position_entries as w WHERE w.article_id = :articleid", nativeQuery = true) + Optional getArticleStock(long articleid); + } diff --git a/prototype/src/main/resources/application.properties b/prototype/src/main/resources/application.properties index 18ec88c..aee1c7d 100644 --- a/prototype/src/main/resources/application.properties +++ b/prototype/src/main/resources/application.properties @@ -16,6 +16,8 @@ spring.jpa.show-sql=true #server.servlet.session.persistent=true # ---------------------------------------- # WEB PROPERTIES +spring.servlet.multipart.max-file-size=10MB +spring.servlet.multipart.max-request-size=10MB # ---------------------------------------- # EMBEDDED SERVER CONFIGURATION (ServerProperties) server.address=::1 diff --git a/prototype/src/main/resources/static/css/ecom.css b/prototype/src/main/resources/static/css/ecom.css index 1d8f125..2a696d2 100644 --- a/prototype/src/main/resources/static/css/ecom.css +++ b/prototype/src/main/resources/static/css/ecom.css @@ -278,7 +278,7 @@ img.s { } img.m { - width: var(--u8); + width: 20rem; } /* diff --git a/prototype/src/main/resources/static/img/product-1.jpg b/prototype/src/main/resources/static/img/product-1.jpg deleted file mode 100644 index 8ea7598..0000000 Binary files a/prototype/src/main/resources/static/img/product-1.jpg and /dev/null differ diff --git a/prototype/src/main/resources/static/img/product-2.jpg b/prototype/src/main/resources/static/img/product-2.jpg deleted file mode 100644 index 427b2f0..0000000 Binary files a/prototype/src/main/resources/static/img/product-2.jpg and /dev/null differ diff --git a/prototype/src/main/resources/static/img/product-3.jpg b/prototype/src/main/resources/static/img/product-3.jpg deleted file mode 100644 index dbc1b2e..0000000 Binary files a/prototype/src/main/resources/static/img/product-3.jpg and /dev/null differ diff --git a/prototype/src/main/resources/static/img/product-4.jpg b/prototype/src/main/resources/static/img/product-4.jpg deleted file mode 100644 index 8f2d857..0000000 Binary files a/prototype/src/main/resources/static/img/product-4.jpg and /dev/null differ diff --git a/prototype/src/main/resources/static/img/product-5.jpg b/prototype/src/main/resources/static/img/product-5.jpg deleted file mode 100644 index 5e0a406..0000000 Binary files a/prototype/src/main/resources/static/img/product-5.jpg and /dev/null differ diff --git a/prototype/src/main/resources/static/img/product-6.jpg b/prototype/src/main/resources/static/img/product-6.jpg deleted file mode 100644 index 05d78c0..0000000 Binary files a/prototype/src/main/resources/static/img/product-6.jpg and /dev/null differ diff --git a/prototype/src/main/resources/static/img/product-7.jpg b/prototype/src/main/resources/static/img/product-7.jpg deleted file mode 100644 index 220140c..0000000 Binary files a/prototype/src/main/resources/static/img/product-7.jpg and /dev/null differ diff --git a/prototype/src/main/resources/static/img/product-8.jpg b/prototype/src/main/resources/static/img/product-8.jpg deleted file mode 100644 index cdb829d..0000000 Binary files a/prototype/src/main/resources/static/img/product-8.jpg and /dev/null differ diff --git a/prototype/src/main/resources/templates/fragments/header.html b/prototype/src/main/resources/templates/fragments/header.html index 7b6ec7c..054c332 100644 --- a/prototype/src/main/resources/templates/fragments/header.html +++ b/prototype/src/main/resources/templates/fragments/header.html @@ -11,7 +11,7 @@
- +
Login @@ -38,7 +38,6 @@ function toggle(id) { document.getElementById(id).classList.toggle("invisible"); } - X
@@ -54,7 +53,6 @@ function toggle(id) { document.getElementById(id).classList.toggle("invisible"); } - X @@ -62,5 +60,4 @@ - diff --git a/prototype/src/main/resources/templates/fragments/intern.html b/prototype/src/main/resources/templates/fragments/intern.html index 79d5f7e..22de534 100644 --- a/prototype/src/main/resources/templates/fragments/intern.html +++ b/prototype/src/main/resources/templates/fragments/intern.html @@ -13,11 +13,7 @@
  • Dashboard
  • -
  • Gelistete Artikel - +
  • Gelistete Artikel
  • Alle Buchungen
      @@ -38,7 +34,7 @@
    • Lieferanten
    • diff --git a/prototype/src/main/resources/templates/fragments/shop.html b/prototype/src/main/resources/templates/fragments/shop.html index 7a87073..d6dea6a 100644 --- a/prototype/src/main/resources/templates/fragments/shop.html +++ b/prototype/src/main/resources/templates/fragments/shop.html @@ -7,15 +7,10 @@ -