feature/reorder_cronjob #27
2
.gitignore
vendored
2
.gitignore
vendored
@ -91,3 +91,5 @@ local.properties
|
||||
prototype/*.db
|
||||
|
||||
prototype/images
|
||||
prototype/data
|
||||
|
||||
|
@ -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")
|
||||
}
|
||||
|
||||
|
BIN
prototype/gradle/wrapper/gradle-wrapper.jar
vendored
BIN
prototype/gradle/wrapper/gradle-wrapper.jar
vendored
Binary file not shown.
@ -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
|
||||
|
22
prototype/gradlew
vendored
Executable file → Normal file
22
prototype/gradlew
vendored
Executable file → Normal file
@ -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"`
|
||||
|
18
prototype/gradlew.bat
vendored
18
prototype/gradlew.bat
vendored
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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() {
|
||||
|
@ -24,6 +24,7 @@ public class LoginIntercepter implements HandlerInterceptor {
|
||||
|
||||
HttpSession session = request.getSession();
|
||||
Object userId = session.getAttribute("userId");
|
||||
Optional<User> 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> user = userRepository.findById((Long) userId);
|
||||
if (user == null)
|
||||
user = userRepository.findById((Long) userId);
|
||||
user.ifPresent(value -> request.setAttribute("user", value));
|
||||
}
|
||||
|
||||
|
@ -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> 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";
|
||||
}
|
||||
}
|
@ -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<UImodelArticles> totals = new ArrayList<UImodelArticles>();
|
||||
|
||||
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<Integer> 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<Integer> 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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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<UImodelOfferedArticle> totals = new ArrayList<UImodelOfferedArticle>();
|
||||
|
||||
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<Integer> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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<Article> commercialArticles = GetRandomArticlesAction.getRandomArticles(3, articleRepository.getAdvertisedArticles());
|
||||
List<Article> 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());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -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<Article> commercialArticles = GetRandomArticlesAction.getRandomArticles(8, articleRepository.getAdvertisedArticles());
|
||||
List<Article> 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<Article> 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";
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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<Article> articles = articleRepository.getArticlesByTerm(term); //search by Term
|
||||
model.addAttribute("articles", articles);
|
||||
} else if (category != null) { //if search by Category
|
||||
List<Article> 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";
|
||||
}
|
||||
}
|
@ -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) {
|
||||
|
@ -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<Category> categories = new HashSet<>();
|
||||
|
||||
@ -46,4 +46,4 @@ public class Article {
|
||||
public int getPriceGross() {
|
||||
return shopPricePerUnitNetCent + getVat();
|
||||
}
|
||||
}
|
||||
}
|
@ -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<Article> articles = new HashSet<>();
|
||||
|
||||
|
||||
public Category() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
public Category (String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
||||
}
|
||||
|
@ -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<Article, Long> {
|
||||
|
||||
@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<Article> 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<Article> 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<Article> 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<Article> getOrderedArticles(long customerId);
|
||||
|
||||
@Query(value = "SELECT a.id FROM articles a WHERE a.related_id = :relatedId", nativeQuery = true)
|
||||
Optional<Integer> 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<Article> 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<Article> getArticlesByCategory(String category);
|
||||
}
|
@ -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<Category, Long> {
|
||||
|
||||
@Query("SELECT a FROM Category a WHERE a.name = :name")
|
||||
Optional<Category> findCategoryByName(@Param("name") String name);
|
||||
|
||||
@Query("SELECT c FROM Category c")
|
||||
List<Category> getCategories();
|
||||
}
|
@ -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<Image, Long> {
|
||||
|
||||
@Query("SELECT i.id FROM Image i WHERE i.path = :path")
|
||||
Optional<Integer> findImageIDByPath(@Param("path") String path);
|
||||
|
||||
@Query("SELECT i FROM Image i WHERE i.id = :imageId")
|
||||
Image findImageById(@Param("imageId") long imageId);
|
||||
|
||||
}
|
@ -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<ArticleOffer, Long> {
|
||||
|
||||
@Query("SELECT a FROM ArticleOffer a")
|
||||
List<ArticleOffer> findAll();
|
||||
|
||||
@Query("SELECT a FROM ArticleOffer a WHERE a.id = :offeredarticleId")
|
||||
ArticleOffer findOfferedArticleById(@Param("offeredarticleId") long offeredarticleId);
|
||||
|
||||
}
|
@ -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<WarehouseBookingPositionSlotEntry, Long> {
|
||||
|
||||
@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<WarehouseBookingPositionSlotEntry> 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<Integer> getArticleStock(long articleid);
|
||||
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -278,7 +278,7 @@ img.s {
|
||||
}
|
||||
|
||||
img.m {
|
||||
width: var(--u8);
|
||||
width: 20rem;
|
||||
}
|
||||
|
||||
/*
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -11,7 +11,7 @@
|
||||
<div class='content-width bar-flex'>
|
||||
<a class="button no-padding" href="/"><img class="logo" th:src="@{/img/ecom-logo-base.svg}"></a>
|
||||
<form class='spacer input-icon secondary' th:action="@{/shop/search}" method="GET">
|
||||
<input type="text" placeholder="Nach Produkten suchen..."/>
|
||||
<input type="text" name="term" placeholder="Nach Produkten suchen..."/>
|
||||
<button>Finden</button>
|
||||
</form>
|
||||
<a th:unless="${user}" class="button" th:href="@{/login}">Login</a>
|
||||
@ -38,7 +38,6 @@
|
||||
function toggle(id) {
|
||||
document.getElementById(id).classList.toggle("invisible");
|
||||
}
|
||||
|
||||
</script>
|
||||
<a class="secondary button error" href="javascript:void(0)" onclick="toggle('error-msg');">X</a>
|
||||
</div>
|
||||
@ -54,7 +53,6 @@
|
||||
function toggle(id) {
|
||||
document.getElementById(id).classList.toggle("invisible");
|
||||
}
|
||||
|
||||
</script>
|
||||
<a class="secondary button info" href="javascript:void(0)" onclick="toggle('info-msg');">X</a>
|
||||
</div>
|
||||
@ -62,5 +60,4 @@
|
||||
</div>
|
||||
</nav>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
@ -13,11 +13,7 @@
|
||||
<ul>
|
||||
<li><a th:href="@{/intern/}">Dashboard</a>
|
||||
</li>
|
||||
<li><a th:href="@{/intern/listedArticles/}">Gelistete Artikel</a>
|
||||
<ul>
|
||||
<li><a th:href="@{/intern/articles/}">Händlerangebote</a>
|
||||
</li>
|
||||
</ul>
|
||||
<li><a th:href="@{/intern/articles/}">Gelistete Artikel</a>
|
||||
</li>
|
||||
<li><a th:href="@{/intern/accounting/}">Alle Buchungen</a>
|
||||
<ul>
|
||||
@ -38,7 +34,7 @@
|
||||
<li><a th:href="@{/intern/suppliers/}">Lieferanten</a>
|
||||
<ul>
|
||||
<li><a th:href="@{/intern/supplierOrders/}">Bestellungen</a></li>
|
||||
<li><a th:href="@{/intern/articles/}">> Händlerangebote</a></li>
|
||||
<li><a th:href="@{/intern/supplierOffers}">> Händlerangebote</a></li>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
|
@ -7,15 +7,10 @@
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<nav th:fragment="sidebar">
|
||||
<nav th:fragment="sidebar (categories)">
|
||||
<h1>Kategorien</h1>
|
||||
<ul class="secondary">
|
||||
<li><a href="/shop/search">Aufnahmegeräte</a></li>
|
||||
<li><a href="/shop/search">Computer</a></li>
|
||||
<li><a href="/shop/search">Fernseher</a></li>
|
||||
<li><a href="/shop/search">Handys</a></li>
|
||||
<li><a href="/shop/search">Unterhaltungselektronik</a></li>
|
||||
<li><a href="/shop/search">Sonstiges</a></li>
|
||||
<li th:each="category: ${categories}"><a th:href="@{/shop/search(category=${category.name})}" th:text="${category.name}"></a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
</body>
|
||||
|
@ -1,140 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de" dir="ltr" xmlns:th="http://www.thymeleaf.org">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=0.75, user-scalable=no">
|
||||
|
||||
<title>Händlerangebote</title>
|
||||
<script th:src="@{/js/filterTable.js}"></script>
|
||||
<link rel="stylesheet" th:href="@{/css/ecom.css}"/>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<nav th:replace="fragments/header :: header">Header</nav>
|
||||
<div class="sidebar-layout content-width">
|
||||
<nav></nav>
|
||||
<div>
|
||||
<h1>Übersicht der von Lieferanten angebotenen Artikel</h1>
|
||||
|
||||
<script th:src="@{/js/back.js}"></script>
|
||||
<div class="back" data-group="intern" data-name="Zurück zur Übersicht der von Lieferanten angebotenen Artikel."
|
||||
data-insert="false"></div>
|
||||
</div>
|
||||
</div>
|
||||
<main class="sidebar-layout content-width">
|
||||
<nav th:replace="fragments/intern :: sidebar"></nav>
|
||||
<div class="content-width">
|
||||
<p>
|
||||
<table id="main-table">
|
||||
<tr>
|
||||
<th colspan="7">
|
||||
<input type="text" placeholder="Filtern" class="smaller jsFilterTable full-width"
|
||||
data-target-id="main-table"></input>
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Hersteller</th>
|
||||
<th>Artikelnummer</th>
|
||||
<th>Lieferant</th>
|
||||
<th>Kaufpreis (Netto)</th>
|
||||
<th>Werbungs-<br/>anfrage</th>
|
||||
<th>Status</th>
|
||||
</tr>
|
||||
<!--**********************************************************-->
|
||||
<tr data-group="5420">
|
||||
<td>Kamera</td>
|
||||
<td>Sonjizu</td>
|
||||
<td>K48431587EX</td>
|
||||
<td colspan="3"></td>
|
||||
<td><a th:href="@{/intern/listedArticles/48670}">Gelistet 44048</a></td>
|
||||
</tr>
|
||||
<tr data-group="5420">
|
||||
<td colspan="3"></td>
|
||||
<td><a th:href="@{/intern/suppliers/48670}">Hans Guck GmbH</a></td>
|
||||
<td>584,50 EUR</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr data-group="5420">
|
||||
<td colspan="3"></td>
|
||||
<td><a th:href="@{/intern/suppliers/48670}">Cheap AG</a></td>
|
||||
<td>84,54 EUR</td>
|
||||
<td>X</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr data-group="5420">
|
||||
<td colspan="3"></td>
|
||||
<td><a th:href="@{/intern/suppliers/48670}">Not Cheap AG</a></td>
|
||||
<td>184,54 EUR</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
|
||||
</tr>
|
||||
|
||||
<!--**********************************************************-->
|
||||
<tr data-group="1233">
|
||||
<td>Earbuds</td>
|
||||
<td>Sonjizu</td>
|
||||
<td>G447#$X</td>
|
||||
<td colspan="3"></td>
|
||||
<td><a th:href="@{/intern/listedArticles/48670}">Gelistet 448</a></td>
|
||||
</tr>
|
||||
<tr data-group="1233">
|
||||
<td colspan="3"></td>
|
||||
<td><a th:href="@{/intern/suppliers/48670}">Cheap AG</a></td>
|
||||
<td>50,54 EUR</td>
|
||||
<td>X</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
|
||||
|
||||
<!--**********************************************************-->
|
||||
<tr data-group="42415">
|
||||
<td>Mundschutz</td>
|
||||
<td>Farma Corp</td>
|
||||
<td>Mu-15415</td>
|
||||
<td colspan="3"></td>
|
||||
<td><a class="button smaller" th:href="@{/intern/listedArticles/48670}">Hinzufügen</a></td>
|
||||
</tr>
|
||||
<tr data-group="42415">
|
||||
<td colspan="3"></td>
|
||||
<td><a th:href="@{/intern/suppliers/48670}">Cheap AG</a></td>
|
||||
<td>150,54 EUR</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
|
||||
</tr>
|
||||
<tr data-group="42415">
|
||||
<td colspan="3"></td>
|
||||
<td><a th:href="@{/intern/suppliers/48670}">Not Cheap AG</a></td>
|
||||
<td>250,54 EUR</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
|
||||
|
||||
<!--**********************************************************-->
|
||||
<tr data-group="4580">
|
||||
<td>Goldbaren</td>
|
||||
<td>Bundesbank</td>
|
||||
<td>G1KG</td>
|
||||
<td colspan="3"></td>
|
||||
<td><a th:href="@{/intern/listedArticles/48670}">Inaktiv 4888</a></td>
|
||||
</tr>
|
||||
<tr data-group="4580">
|
||||
<td colspan="3"></td>
|
||||
<td><a th:href="@{/intern/suppliers/48670}">Cheap AG</a></td>
|
||||
<td>10000,54 EUR</td>
|
||||
<td>X</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</table>
|
||||
</p>
|
||||
</div>
|
||||
</main>
|
||||
<footer th:replace="fragments/footer :: footer"></footer>
|
||||
</body>
|
||||
|
||||
</html>
|
@ -1,119 +1,109 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de" dir="ltr" xmlns:th="http://www.thymeleaf.org">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=0.75, user-scalable=no">
|
||||
|
||||
<title>Gelistete Artikel</title>
|
||||
<script th:src="@{/js/filterTable.js}"></script>
|
||||
<link rel="stylesheet" th:href="@{/css/ecom.css}"/>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<nav th:replace="fragments/header :: header">Header</nav>
|
||||
<div class="sidebar-layout content-width">
|
||||
<nav></nav>
|
||||
<div>
|
||||
<h1>Gelisteter Artikel 8450</h1>
|
||||
|
||||
<script th:src="@{/js/back.js}"></script>
|
||||
<div class="back" data-group="intern" data-insert="true"></div>
|
||||
</div>
|
||||
</div>
|
||||
<main class="sidebar-layout content-width">
|
||||
<nav th:replace="fragments/intern :: sidebar"></nav>
|
||||
<div class="content-width">
|
||||
<h2>Gelisteter Artikel 8450</h2>
|
||||
<form class="detailgrid">
|
||||
<p class="m">
|
||||
<label for="title">Titel</label>
|
||||
<input class=" full-width" type="text" name="title" value="Kamera"/>
|
||||
</p>
|
||||
<p class="s">
|
||||
<label for="ref-article">Refernzierter Artikel</label>
|
||||
<input class="" type="text" name="ref-article" value="8405" disabled/>
|
||||
<td><a th:href="@{/intern/articles/#q=%2044048}">Details</a></td>
|
||||
</p>
|
||||
<div class="spacer"></div>
|
||||
<div class="m">
|
||||
<p>
|
||||
<label for="img">Bild Hochladen</label>
|
||||
<input class="full-width" type="file" name="img"/>
|
||||
</p>
|
||||
<p>
|
||||
<img th:src="@{/img/product-1.jpg}" class="m"/>
|
||||
</p>
|
||||
</div>
|
||||
<div class="s">
|
||||
<p>
|
||||
<label for="price">Preis (Netto)</label>
|
||||
<input class="" type="number" step="0.01" name="price" value="84.45"/> EUR <br/>
|
||||
(19% Mwst.)
|
||||
<!-- Info von article ref--> <br/>
|
||||
= 105.98 EUR Brutto
|
||||
</p>
|
||||
<p>
|
||||
<label for="max-price-buy">Maximaler Einkaufspreis (Netto)</label>
|
||||
<input class="" type="number" step="0.01" name="price" value="80.98"/> EUR
|
||||
</p>
|
||||
<div>
|
||||
<fieldset>
|
||||
<input type="radio" name="autobuy" value="true" id="autobuy-yes" checked required>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=0.75, user-scalable=no">
|
||||
<title>Bearbeiten: Artikel</title>
|
||||
<script th:src="@{/js/filterTable.js}"></script>
|
||||
<link rel="stylesheet" th:href="@{/css/ecom.css}"/>
|
||||
</head>
|
||||
<body>
|
||||
<nav th:replace="fragments/header :: header">Header</nav>
|
||||
<div class="sidebar-layout content-width">
|
||||
<nav></nav>
|
||||
<div>
|
||||
<h1>Artikel bearbeiten</h1>
|
||||
<script th:src="@{/js/back.js}"></script>
|
||||
<div class="back" data-group="intern" data-insert="true"></div>
|
||||
</div>
|
||||
</div>
|
||||
<main class="sidebar-layout content-width">
|
||||
<nav th:replace="fragments/intern :: sidebar"></nav>
|
||||
<div class="content-width">
|
||||
<h2>Gelisteter Artikel ID <span th:text="${ArticleID.id}"></span></h2>
|
||||
<form class="detailgrid" action="#" th:action="@{/intern/articles/{id}/saveChanges(id = ${ArticleID.id})}" th:object="${ArticleID}" method="POST" enctype="multipart/form-data">
|
||||
<p class="m">
|
||||
<label for="title">Titel</label>
|
||||
<input class=" full-width" type="text" id="title" name="title" required="required" pattern="[A-Za-z0-9]{1,20}" th:value="${ArticleID.title}"/>
|
||||
</p>
|
||||
<p class="s">
|
||||
<label for="ref-article">Refernzierter Artikel</label>
|
||||
<input class="" type="text" id="ref_disabled" th:value="${ArticleID.offer_id}" disabled/>
|
||||
|
||||
<input type="hidden" id="ref_hidden" th:value="${ArticleID.offer_id}" name="ref-article" />
|
||||
|
||||
<td><a th:href="${'/intern/supplierOffers/#q=' + {ArticleID.id}}">Details</a></td>
|
||||
</p>
|
||||
<div class="spacer"></div>
|
||||
<div class="m">
|
||||
<p>
|
||||
<label for="img">Bild Hochladen</label>
|
||||
<input class="full-width" type="file" id="image" name="img"/>
|
||||
</p>
|
||||
<p>
|
||||
<img th:src="@{/shop/articles/{id}/image.jpg(id=${ArticleID.id})}" class="m"/>
|
||||
</p>
|
||||
</div>
|
||||
<div class="s">
|
||||
<p>
|
||||
<label for="price">Preis (Netto)</label>
|
||||
<input class="" type="number" step="0.01" name="price_netto" th:value="${ArticleID.price_netto}"/> EUR <br/>
|
||||
(19% Mwst.)
|
||||
<!-- Info von article ref--> <br/>
|
||||
= <span th:text="${ArticleID.price}"></span> EUR Brutto
|
||||
</p>
|
||||
<p>
|
||||
<label for="max-price-buy">Maximaler Einkaufspreis (Netto)</label>
|
||||
<input class="" type="number" id="reorderMaxPrice" step="0.01" name="reorderMaxPrice" th:value="${ArticleID.reorderMaxPrice}"/> EUR
|
||||
</p>
|
||||
<div>
|
||||
<fieldset>
|
||||
<input type="radio" name="autobuy" value="true" id="autobuy-yes" th:checked="${ArticleID.shouldReorder}" required>
|
||||
<label for="autobuy-yes"> Automatisch nachbestellen.</label> <br/>
|
||||
<input type="radio" name="autobuy" value="false" id="autobuy-no" required>
|
||||
<input type="radio" name="autobuy" value="false" id="autobuy-no" th:checked="${!ArticleID.shouldReorder}" required>
|
||||
<label for="autobuy-no"> Nicht mehr nachkaufen.</label> <br/>
|
||||
</fieldset>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
</div>
|
||||
<div class="m">
|
||||
<label for="tags">Kategorien</label>
|
||||
<p>
|
||||
Bitte jede Kategorien in eine eigene Zeile
|
||||
</p>
|
||||
<textarea name="categories" id="categories" class="full-width" rows="6"th:inline="text">[[${ArticleID.categorie}]]
|
||||
|
||||
<div class="m">
|
||||
<label for="tags">Kategorien</label>
|
||||
<p>
|
||||
Bitte jede Kategorien in eine eigene Zeile
|
||||
</p>
|
||||
<textarea name="tags" class="full-width" rows="6">
|
||||
Überwachung
|
||||
Elektronik
|
||||
</textarea>
|
||||
</div>
|
||||
|
||||
<div class="s">
|
||||
<p>
|
||||
<label for="price">Einheiten pro Lagerplatz</label>
|
||||
<input class="" type="number" name="units-per-slot" value="20"/>
|
||||
</p>
|
||||
<p>
|
||||
<b>Lagerbestand: 12</b>
|
||||
</p>
|
||||
<p>
|
||||
Der Wert wird nur für zukünftige Lagerbuchungen verwendet.
|
||||
Bei Problemen kann können Einheiten aus- und wieder eingebucht werden.
|
||||
<!-- TODO: set link g-->
|
||||
</p>
|
||||
<p>
|
||||
<a href="/todo" class="button smaller">Lagerbuchung</a>
|
||||
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<p class="l">
|
||||
<label for="description">Beschreibung</label>
|
||||
<textarea name="description" class="full-width" rows="15">
|
||||
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!
|
||||
</textarea>
|
||||
</p>
|
||||
<div class="l">
|
||||
<button type="submit">Änderungen speichern</button>
|
||||
<button type="reset">Zurücksetzen</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</main>
|
||||
<footer th:replace="fragments/footer :: footer"></footer>
|
||||
</body>
|
||||
|
||||
</div>
|
||||
<div class="s">
|
||||
<p>
|
||||
<label for="price">Einheiten pro Lagerplatz</label>
|
||||
<input class="" type="number" id="units-per-slot" name="units-per-slot" th:value="${ArticleID.warehouseUnitsPerSlot}"/>
|
||||
</p>
|
||||
<p>
|
||||
<b>Lagerbestand: <span th:text="${ArticleID.stock}"></span></b>
|
||||
</p>
|
||||
<p>
|
||||
Der Wert wird nur für zukünftige Lagerbuchungen verwendet.
|
||||
Bei Problemen kann können Einheiten aus- und wieder eingebucht werden.
|
||||
<!-- TODO: set link g-->
|
||||
</p>
|
||||
<p>
|
||||
<a href="/todo" class="button smaller">Lagerbuchung</a>
|
||||
</p>
|
||||
</div>
|
||||
<p class="l">
|
||||
<label for="description">Beschreibung</label>
|
||||
<textarea name="description" id="description" class="full-width" rows="15" th:inline="text">[[${ArticleID.description}]]
|
||||
</textarea>
|
||||
</p>
|
||||
<div class="l">
|
||||
<button type="submit">Änderungen speichern</button>
|
||||
<button type="reset">Zurücksetzen</button>
|
||||
<button onclick="history.back()">Änderungen verwerfen</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</main>
|
||||
<footer th:replace="fragments/footer :: footer"></footer>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -1,109 +1,69 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de" dir="ltr" xmlns:th="http://www.thymeleaf.org">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=0.75, user-scalable=no">
|
||||
|
||||
<title>Gelistete Artikel</title>
|
||||
<script th:src="@{/js/filterTable.js}"></script>
|
||||
<link rel="stylesheet" th:href="@{/css/ecom.css}"/>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<nav th:replace="fragments/header :: header">Header</nav>
|
||||
<div class="sidebar-layout content-width">
|
||||
<nav></nav>
|
||||
<div>
|
||||
<h1>Gelistete Artikel</h1>
|
||||
|
||||
<script th:src="@{/js/back.js}"></script>
|
||||
<div class="back" data-group="intern" data-name="Zurück zu den gelisteten Artikeln." data-insert="false"></div>
|
||||
</div>
|
||||
</div>
|
||||
<main class="sidebar-layout content-width">
|
||||
<nav th:replace="fragments/intern :: sidebar"></nav>
|
||||
<div class="content-width">
|
||||
<h2>Artikel Hinzufügen</h2>
|
||||
<p>
|
||||
Weitere Artikel können über Artikelübersicht gelistet werden.
|
||||
<a class="button smaller" th:href="@{/intern/articles/}"> Jetzt Hinzufügen </a>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<table id="main-table">
|
||||
<tr>
|
||||
<th colspan="8">
|
||||
<input type="text" placeholder="Filtern" class="smaller jsFilterTable full-width"
|
||||
data-target-id="main-table"></input>
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Bild</th>
|
||||
<th>Name</th>
|
||||
<th>Preis</th>
|
||||
<th>(Netto)</th>
|
||||
<th>Kategorien</th>
|
||||
<th>Lagerbestand (Aktiv)</th>
|
||||
<th>Artikel</th>
|
||||
<th>Id (bearbeiten)</th>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><img th:src="@{/img/product-1.jpg}" class="s"/></td>
|
||||
<td>Kamera</td>
|
||||
<td>100,50 EUR</td>
|
||||
<td> (84.45 EUR)</td>
|
||||
<td>Úberwachung, Elektronik</td>
|
||||
<td>301 <span class="checked"></span></td>
|
||||
<td><a th:href="@{/intern/articles/#q=%2044048}">5051</a></td>
|
||||
<td><a th:href="@{/intern/listedArticles/45015}">890</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img th:src="@{/img/product-2.jpg}" class="s"/></td>
|
||||
<td>Earbuds</td>
|
||||
<td>63,95 EUR</td>
|
||||
<td>(53,73 EUR)</td>
|
||||
<td>Kopfhörer, Elektronik</td>
|
||||
<td>12 <span class="checked"></span></td>
|
||||
<td><a th:href="@{/intern/articles/#q=%2044048}">840</a></td>
|
||||
<td><a th:href="@{/intern/listedArticles/45015}">13850</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img th:src="@{/img/product-3.jpg}" class="s"/></td>
|
||||
<td>USB-Magic Light</td>
|
||||
<td>11,90 EUR</td>
|
||||
<td> (10,00 EUR)</td>
|
||||
<td>Sonstiges, Elektronik</td>
|
||||
<td>3<span class="unchecked"></span></td>
|
||||
<td><a th:href="@{/intern/articles/#q=%2044048}">8401</a></td>
|
||||
<td><a th:href="@{/intern/listedArticles/45015}">5784</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img th:src="@{/img/product-4.jpg}" class="s"/></td>
|
||||
<td>3D Magic Stativ</td>
|
||||
<td>15,99 EUR</td>
|
||||
<td> (13.44 EUR)</td>
|
||||
<td>Úberwachung, Elektronik</td>
|
||||
<td>4<span class="checked"></span></td>
|
||||
<td><a th:href="@{/intern/articles/#q=%2044048}">2135</a></td>
|
||||
<td><a th:href="@{/intern/listedArticles/45015}">4564</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img th:src="@{/img/product-5.jpg}" class="s"/></td>
|
||||
<td>Ersatzfernbedinung</td>
|
||||
<td>7,95 EUR</td>
|
||||
<td> (6.68 EUR)</td>
|
||||
<td>Úberwachung, Elektronik</td>
|
||||
<td>0<span class="checked"></span></td>
|
||||
<td><a th:href="@{/intern/articles/#q=%2044048}">4565</a></td>
|
||||
<td><a th:href="@{/intern/listedArticles/45015}">4566</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
<p>
|
||||
</div>
|
||||
</main>
|
||||
<footer th:replace="fragments/footer :: footer"></footer>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=0.75, user-scalable=no">
|
||||
<title>Gelistete Artikel</title>
|
||||
<script th:src="@{/js/filterTable.js}"></script>
|
||||
<link rel="stylesheet" th:href="@{/css/ecom.css}"/>
|
||||
</head>
|
||||
<body>
|
||||
<nav th:replace="fragments/header :: header">Header</nav>
|
||||
<div class="sidebar-layout content-width">
|
||||
<nav></nav>
|
||||
<div>
|
||||
<h1>Gelistete Artikel</h1>
|
||||
<script th:src="@{/js/back.js}"></script>
|
||||
<div class="back" data-group="intern" data-name="Zurück zu den gelisteten Artikeln." data-insert="false"></div>
|
||||
</div>
|
||||
</div>
|
||||
<main class="sidebar-layout content-width">
|
||||
<nav th:replace="fragments/intern :: sidebar"></nav>
|
||||
<div class="content-width">
|
||||
<p>
|
||||
Weitere Artikel können über Artikelübersicht der Lieferanten hinzugefügt werden.
|
||||
<a class="button smaller" th:href="@{/intern/supplierOffers}"> Jetzt Hinzufügen </a>
|
||||
</p>
|
||||
<p>
|
||||
<table id="main-table">
|
||||
<tr>
|
||||
<th colspan="9">
|
||||
<input type="text" placeholder="Filtern" class="smaller jsFilterTable full-width"
|
||||
data-target-id="main-table"></input>
|
||||
</th>
|
||||
</tr>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Bild</th>
|
||||
<th>Name</th>
|
||||
<th>Preis</th>
|
||||
<th>(Netto)</th>
|
||||
<th>Kategorien</th>
|
||||
<th>Lagerbestand</th>
|
||||
<th>Angebots ID</th>
|
||||
<th>Artikel ID</th>
|
||||
<th>Aktion</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr th:each="article : ${ListedArticles}">
|
||||
<td><img th:src="@{/shop/articles/{id}/image.jpg(id=${article.id})}" class="s"/></td>
|
||||
<td><span th:text="${article.title}"></span></td>
|
||||
<td><span th:text="${article.price}"></span> €</td>
|
||||
<td><span th:text="${article.price_netto}"></span> €</td>
|
||||
<td><span th:text="${article.categorie}"></span></td>
|
||||
<td><span th:text="${article.stock}"></span></td>
|
||||
<td><a th:href="${'/intern/supplierOffers/#q=' + {article.title}}" th:text="${article.offer_id}"></a></td>
|
||||
<td><a th:href="@{/intern/articles/{id}(id = ${article.id})}" th:text="${article.id}"></a></td>
|
||||
<td>
|
||||
<form th:action="@{/intern/articles/{id}(id = ${article.id})}"><input type="submit" value="Bearbeiten" /></form>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>
|
||||
</div>
|
||||
</main>
|
||||
<footer th:replace="fragments/footer :: footer"></footer>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,69 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de" dir="ltr" xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=0.75, user-scalable=no">
|
||||
<title>Händlerangebote</title>
|
||||
<script th:src="@{/js/filterTable.js}"></script>
|
||||
<link rel="stylesheet" th:href="@{/css/ecom.css}"/>
|
||||
</head>
|
||||
<body>
|
||||
<nav th:replace="fragments/header :: header">Header</nav>
|
||||
<div class="sidebar-layout content-width">
|
||||
<nav></nav>
|
||||
<div>
|
||||
<h1>Übersicht der Angebote von Lieferanten</h1>
|
||||
<script th:src="@{/js/back.js}"></script>
|
||||
<div class="back" data-group="intern" data-name="Zurück zur Übersicht der von Lieferanten angebotenen Artikel."
|
||||
data-insert="false"></div>
|
||||
</div>
|
||||
</div>
|
||||
<main class="sidebar-layout content-width">
|
||||
<nav th:replace="fragments/intern :: sidebar"></nav>
|
||||
<div class="content-width">
|
||||
<p>
|
||||
<table id="main-table">
|
||||
<tr>
|
||||
<th colspan="7">
|
||||
<input type="text" placeholder="Filtern" class="smaller jsFilterTable full-width" data-target-id="main-table"></input>
|
||||
</th>
|
||||
</tr>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Hersteller</th>
|
||||
<th>Artikelnummer</th>
|
||||
<th>Lieferant</th>
|
||||
<th>Kaufpreis (Netto)</th>
|
||||
<th>Werbungs-<br/>anfrage</th>
|
||||
<th>Status</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr th:each="article : ${OfferedArticles}">
|
||||
<td><span th:text="${article.title}"></span></td>
|
||||
<td><span th:text="${article.manufacturer}"></span></td>
|
||||
<td><span th:text="${article.articlenumber}"></span></td>
|
||||
<td><a th:href="@{/intern/suppliers/{id}(id = ${article.supplierId})}" th:text="${article.supplierName}"></a></td>
|
||||
<td><span th:text="${article.price}"></span> €</td>
|
||||
<td><span th:text="${article.ads}"></span></td>
|
||||
<td>
|
||||
<div th:if="${article.offerIsListed}">
|
||||
<a th:href="@{/intern/articles/{id}(id = ${article.listedArticleId})}">Artikel gelistet</a>
|
||||
</div>
|
||||
<!-- ELSE -->
|
||||
<div th:unless="${article.offerIsListed}">
|
||||
<form class="detailgrid" action="#" th:action="@{/intern/articles/addArticle/{id}(id = ${article.offer_id})}" method="POST">
|
||||
<input type="submit" value="Hinzufügen" />
|
||||
</form>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</p>
|
||||
</div>
|
||||
</main>
|
||||
<footer th:replace="fragments/footer :: footer"></footer>
|
||||
</body>
|
||||
</html>
|
@ -14,7 +14,7 @@
|
||||
<nav th:replace="fragments/header :: header">Header</nav>
|
||||
<main class=" content-width">
|
||||
<div class="sidebar-layout" style="min-height: 75vh;">
|
||||
<nav th:replace="fragments/shop :: sidebar"></nav>
|
||||
<nav th:replace="fragments/shop :: sidebar(categories=${categories})"></nav>
|
||||
<div class="content-width">
|
||||
<div class="detailgrid">
|
||||
<div class="s">
|
||||
@ -23,7 +23,9 @@
|
||||
<script th:src="@{/js/back.js}"></script>
|
||||
<div class="back" data-group="shop" data-insert="true"></div>
|
||||
|
||||
<h2><span th:text="${#numbers.formatDecimal(article.getPriceGross() * 0.01, 1, 'POINT', 2, 'COMMA')}"></span><span> EUR</span></h2>
|
||||
<h2><span
|
||||
th:text="${#numbers.formatDecimal(article.getPriceGross() * 0.01, 1, 'POINT', 2, 'COMMA')}"></span><span> EUR</span>
|
||||
</h2>
|
||||
<p th:text="${article.description}"></p>
|
||||
</div>
|
||||
<div class="s">
|
||||
@ -32,7 +34,9 @@
|
||||
<div class="s"></div>
|
||||
<form class="s" method="POST">
|
||||
<div class="detailgrid m">
|
||||
<h2><span th:text="${#numbers.formatDecimal(article.getPriceGross() * 0.01, 1, 'POINT', 2, 'COMMA')}"></span><span> EUR</span></h2>
|
||||
<h2><span
|
||||
th:text="${#numbers.formatDecimal(article.getPriceGross() * 0.01, 1, 'POINT', 2, 'COMMA')}"></span><span> EUR</span>
|
||||
</h2>
|
||||
<div>
|
||||
<label class="nolinebreak">Menge:</label>
|
||||
<select name="quantity" size="1">
|
||||
@ -55,10 +59,13 @@
|
||||
<div>
|
||||
<h1>Weitere Schnäppchen</h1>
|
||||
<div class='grid m base shadow'>
|
||||
<section th:each="article: ${commercialArticles}"><a th:href="@{/shop/articles/{id}(id = ${article.id})}" class="section">
|
||||
<section th:each="article: ${commercialArticles}"><a
|
||||
th:href="@{/shop/articles/{id}(id = ${article.id})}" class="section">
|
||||
<img th:src="@{/shop/articles/{id}/image.jpg(id=${article.id})}"/>
|
||||
<h2 th:text="${article.title}"></h2>
|
||||
<p class='price'><span th:text="${#numbers.formatDecimal(article.getPriceGross() * 0.01, 1, 'POINT', 2, 'COMMA')}"></span><span> EUR</span></p>
|
||||
<p class='price'><span
|
||||
th:text="${#numbers.formatDecimal(article.getPriceGross() * 0.01, 1, 'POINT', 2, 'COMMA')}"></span><span> EUR</span>
|
||||
</p>
|
||||
<p th:text="${article.description}"></p>
|
||||
</a>
|
||||
</section>
|
||||
|
@ -25,9 +25,11 @@
|
||||
<a th:href="@{/shop/articles/{id}(id=${article.id})}" class="section">
|
||||
|
||||
<img th:src="@{/shop/articles/{id}/image.jpg(id=${article.id})}"/>
|
||||
<h2 th:text="${article.title}" />
|
||||
<p class='price'><span th:text="${#numbers.formatDecimal(article.getPriceGross() * 0.01, 1, 'POINT', 2, 'COMMA')}"></span><span> EUR</span></p>
|
||||
<p th:text="${article.description}" />
|
||||
<h2 th:text="${article.title}"/>
|
||||
<p class='price'><span
|
||||
th:text="${#numbers.formatDecimal(article.getPriceGross() * 0.01, 1, 'POINT', 2, 'COMMA')}"></span><span> EUR</span>
|
||||
</p>
|
||||
<p th:text="${article.description}"/>
|
||||
</a>
|
||||
</section>
|
||||
<section class="spacer"></section>
|
||||
@ -57,7 +59,7 @@
|
||||
|
||||
<!-- If User is logged in but hasn't ordered anything yet-->
|
||||
<div th:if="${isLoggedIn == true and hasOrders == false}">
|
||||
<h1>Jetzt Shoppen und Empfehlungen erhalten!</h1>
|
||||
<h2>Jetzt Shoppen und Empfehlungen erhalten!</h2>
|
||||
</div>
|
||||
|
||||
<!-- If User is logged in and has ordered something before-->
|
||||
@ -67,9 +69,11 @@
|
||||
<a th:href="@{/shop/articles/{id}(id=${article.id})}" class="section">
|
||||
|
||||
<img th:src="@{/shop/articles/{id}/image.jpg(id=${article.id})}"/>
|
||||
<h2 th:text="${article.title}" />
|
||||
<p class='price'><span th:text="${#numbers.formatDecimal(article.getPriceGross() * 0.01, 1, 'POINT', 2, 'COMMA')}"></span><span> EUR</span></p>
|
||||
<p th:text="${article.description}" />
|
||||
<h2 th:text="${article.title}"/>
|
||||
<p class='price'><span
|
||||
th:text="${#numbers.formatDecimal(article.getPriceGross() * 0.01, 1, 'POINT', 2, 'COMMA')}"></span><span> EUR</span>
|
||||
</p>
|
||||
<p th:text="${article.description}"/>
|
||||
</a>
|
||||
</section>
|
||||
</div>
|
||||
|
@ -21,70 +21,29 @@
|
||||
</div>
|
||||
</div>
|
||||
<main class="sidebar-layout content-width">
|
||||
<nav th:replace="fragments/shop :: sidebar"></nav>
|
||||
<nav th:replace="fragments/shop :: sidebar(categories=${categories})"></nav>
|
||||
<div class="content-width">
|
||||
<div class='grid m condensed'>
|
||||
<section><a th:href="@{/shop/articles/1234}" class="section">
|
||||
<img th:src="@{/img/product-1.jpg}">
|
||||
<h2>Tolle Kamera</h2>
|
||||
<p class='price'> 25.14 EUR</p>
|
||||
<p>
|
||||
Eine TOLLE Kamera <br>
|
||||
Jaja du denkst jetzt bestimmt: "Bei dem Preis kann sie gar nich sooo TOLL sein". <br>
|
||||
Aber glaub mir, sie is echt echt TOLL! <br>
|
||||
Indianerehrenwort!
|
||||
</p>
|
||||
</a>
|
||||
</section>
|
||||
<div class='grid m condensed' th:if="${articles.size() != 0}">
|
||||
<section th:each="article: ${articles}">
|
||||
<a th:href="@{/shop/articles/{id}(id=${article.id})}" class="section">
|
||||
|
||||
<section><a th:href="@{/shop/articles/1234}" class="section">
|
||||
<img th:src="@{/img/product-2.jpg}">
|
||||
<h2>Bluetooth Kopfhörer</h2>
|
||||
<p class='price'> 10.14 EUR</p>
|
||||
<p>
|
||||
Sind halt Kopfhörer ohne Kabel, mehr gibts da nich zu sagen.
|
||||
</p>
|
||||
</a>
|
||||
<img th:src="@{/shop/articles/{id}/image.jpg(id=${article.id})}"/>
|
||||
<h2 th:text="${article.title}"/>
|
||||
<p class='price'><span
|
||||
th:text="${#numbers.formatDecimal(article.getPriceGross() * 0.01, 1, 'POINT', 2, 'COMMA')}"></span><span> EUR</span>
|
||||
</p>
|
||||
<p th:text="${article.description}"/>
|
||||
</a>
|
||||
</section>
|
||||
|
||||
<section><a th:href="@{/shop/articles/1234}" class="section">
|
||||
<img th:src="@{/img/product-3.jpg}">
|
||||
<h2>???</h2>
|
||||
<p class='price'> 25.14 EUR</p>
|
||||
<p>
|
||||
Ich weiß selbst nich was das genau sein soll.<br>
|
||||
Wenn dus willst kannst es gern haben, musst nur das Geld überweisen.
|
||||
</p>
|
||||
</a>
|
||||
</section>
|
||||
|
||||
<section><a th:href="@{/shop/articles/1234}" class="section">
|
||||
<img th:src="@{/img/product-4.jpg}">
|
||||
<h2>Kamera Stativ.</h2>
|
||||
<p class='price'> 25.14 EUR</p>
|
||||
<p>
|
||||
Das Stativ der Zukunft! Jetzt kaufen und verwenden für
|
||||
wackelfreie Bilder aus der Zukunft!.
|
||||
</p>
|
||||
</a>
|
||||
</section>
|
||||
|
||||
<section><a th:href="@{/shop/articles/1234}" class="section">
|
||||
<img th:src="@{/img/product-5.jpg}">
|
||||
<h2>Bluetooth Ersatzfernbedinung</h2>
|
||||
<p class='price'> 10.14 EUR</p>
|
||||
<p>
|
||||
Kann alles und jeden ausknippsen.
|
||||
</p>
|
||||
</a>
|
||||
</section>
|
||||
|
||||
|
||||
<section class="spacer"></section>
|
||||
<section class="spacer"></section>
|
||||
<section class="spacer"></section>
|
||||
<section class="spacer"></section>
|
||||
</div>
|
||||
<div th:if="${articles.size() == 0}">
|
||||
<h2>Keine Ergebnisse für diesen Suchterm gefunden!</h2>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
<footer th:replace="fragments/footer :: footer"></footer>
|
||||
|
Reference in New Issue
Block a user