Merge remote-tracking branch 'origin/master' into feature/reorder_cronjob
							
								
								
									
										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
									
									
								
							
							
						
						@ -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
									
								
							
							
						
						@ -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
									
									
								
							
							
						
						@ -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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
| 
		 Before Width: | Height: | Size: 13 KiB  | 
| 
		 Before Width: | Height: | Size: 18 KiB  | 
| 
		 Before Width: | Height: | Size: 15 KiB  | 
| 
		 Before Width: | Height: | Size: 5.5 KiB  | 
| 
		 Before Width: | Height: | Size: 9.1 KiB  | 
| 
		 Before Width: | Height: | Size: 14 KiB  | 
| 
		 Before Width: | Height: | Size: 12 KiB  | 
| 
		 Before Width: | Height: | Size: 8.7 KiB  | 
@ -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>
 | 
			
		||||
 | 
			
		||||