implement checkout for non logged in users.
This commit is contained in:
		@ -63,6 +63,7 @@ public class ShopArticleController {
 | 
			
		||||
                                      @RequestAttribute(value = "shoppingCart") ShoppingCart shoppingCart,
 | 
			
		||||
                                      @PathVariable("id") Long id,
 | 
			
		||||
                                      @RequestParam("quantity") Integer quantity,
 | 
			
		||||
                                      @RequestParam(value = "set_amount", required = false) Boolean setAmount,
 | 
			
		||||
                                      @RequestParam("fastcheckout") Boolean fastcheckout
 | 
			
		||||
    ) {
 | 
			
		||||
 | 
			
		||||
@ -71,12 +72,16 @@ public class ShopArticleController {
 | 
			
		||||
            throw new RuntimeException("Article not found!");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        shoppingCart.addArticle(article.get(), quantity);
 | 
			
		||||
        if (setAmount != null && setAmount) {
 | 
			
		||||
            shoppingCart.setArticleCount(article.get(), quantity);
 | 
			
		||||
        } else {
 | 
			
		||||
            shoppingCart.addArticle(article.get(), quantity);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (!fastcheckout) {
 | 
			
		||||
            return "shop/articles/post_add";
 | 
			
		||||
        } else {
 | 
			
		||||
            return "shop/checkout";
 | 
			
		||||
            return "redirect:/shop/checkout";
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,23 +1,73 @@
 | 
			
		||||
package org.hso.ecommerce.controller.shop;
 | 
			
		||||
 | 
			
		||||
import org.hso.ecommerce.entities.shop.Article;
 | 
			
		||||
import org.hso.ecommerce.entities.shop.ShoppingCart;
 | 
			
		||||
import org.hso.ecommerce.repos.shop.ArticleRepository;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.stereotype.Controller;
 | 
			
		||||
import org.springframework.web.bind.annotation.GetMapping;
 | 
			
		||||
import org.springframework.web.bind.annotation.PostMapping;
 | 
			
		||||
import org.springframework.web.bind.annotation.RequestAttribute;
 | 
			
		||||
import org.springframework.web.bind.annotation.RequestMapping;
 | 
			
		||||
 | 
			
		||||
import javax.servlet.http.HttpServletRequest;
 | 
			
		||||
import javax.servlet.http.HttpSession;
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.TreeMap;
 | 
			
		||||
 | 
			
		||||
@Controller
 | 
			
		||||
@RequestMapping("/shop/")
 | 
			
		||||
public class ShopCheckoutController {
 | 
			
		||||
 | 
			
		||||
    @Autowired
 | 
			
		||||
    private final ArticleRepository articleRepository = null;
 | 
			
		||||
 | 
			
		||||
    @GetMapping("/checkout")
 | 
			
		||||
    public String shopCheckout(HttpSession session, HttpServletRequest request) {
 | 
			
		||||
    public String shopCheckout(HttpSession session,
 | 
			
		||||
                               HttpServletRequest request,
 | 
			
		||||
                               @RequestAttribute(value = "shoppingCart") ShoppingCart shoppingCart) {
 | 
			
		||||
        session.setAttribute("afterLogin", request.getRequestURI());
 | 
			
		||||
 | 
			
		||||
        CheckoutListTotals totals = new CheckoutListTotals();
 | 
			
		||||
        ArrayList<CheckoutListItem> items = new ArrayList<>();
 | 
			
		||||
        for (ShoppingCart.ShoppingCartItem item : shoppingCart.getItems()) {
 | 
			
		||||
            Article article = articleRepository.findById(item.getArticleId()).get();
 | 
			
		||||
 | 
			
		||||
            totals.addItem(article, item.getAmount());
 | 
			
		||||
            items.add(new CheckoutListItem(item.getAmount(), article));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        request.setAttribute("checkoutItems", items);
 | 
			
		||||
        request.setAttribute("checkoutTotals", totals);
 | 
			
		||||
 | 
			
		||||
        return "shop/checkout";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static class CheckoutListTotals {
 | 
			
		||||
        public int net;
 | 
			
		||||
        public TreeMap<Integer, Integer> vatAmounts = new TreeMap<>();
 | 
			
		||||
        public int total;
 | 
			
		||||
 | 
			
		||||
        void addItem(Article article, int amount) {
 | 
			
		||||
            net += article.shopPricePerUnitNetCent * amount;
 | 
			
		||||
            Integer vatPos = vatAmounts.getOrDefault(article.related.vatPercent, 0) + article.getVat() * amount;
 | 
			
		||||
            vatAmounts.put(article.related.vatPercent, vatPos);
 | 
			
		||||
            total += article.getPriceGross() * amount;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static class CheckoutListItem {
 | 
			
		||||
        public int amount;
 | 
			
		||||
        public Article article;
 | 
			
		||||
        public int total;
 | 
			
		||||
 | 
			
		||||
        public CheckoutListItem(int amount, Article article) {
 | 
			
		||||
            this.amount = amount;
 | 
			
		||||
            this.article = article;
 | 
			
		||||
            this.total = amount * article.getPriceGross();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @PostMapping("/checkoutFinish")
 | 
			
		||||
    public String shopCheckoutFinish() {
 | 
			
		||||
        return "shop/checkoutFinish";
 | 
			
		||||
 | 
			
		||||
@ -37,4 +37,12 @@ public class Article {
 | 
			
		||||
    @ManyToMany
 | 
			
		||||
    @JoinTable(name = "article_categories_bindings")
 | 
			
		||||
    public Set<Category> categories = new HashSet<>();
 | 
			
		||||
 | 
			
		||||
    public int getVat() {
 | 
			
		||||
        return (shopPricePerUnitNetCent * related.vatPercent) / 100;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public int getPriceGross() {
 | 
			
		||||
        return shopPricePerUnitNetCent + getVat();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,7 @@
 | 
			
		||||
package org.hso.ecommerce.entities.shop;
 | 
			
		||||
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
// Not a db entity. Just for session storage
 | 
			
		||||
public class ShoppingCart {
 | 
			
		||||
@ -13,6 +14,10 @@ public class ShoppingCart {
 | 
			
		||||
        items = new ArrayList<>();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public List<ShoppingCartItem> getItems() {
 | 
			
		||||
        return items;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public int getItemCount() {
 | 
			
		||||
        int count = 0;
 | 
			
		||||
 | 
			
		||||
@ -40,7 +45,25 @@ public class ShoppingCart {
 | 
			
		||||
        items.add(new ShoppingCartItem(quantity, article));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static class ShoppingCartItem {
 | 
			
		||||
    public void setArticleCount(Article article, Integer quantity) {
 | 
			
		||||
        this.revision++;
 | 
			
		||||
 | 
			
		||||
        boolean found = false;
 | 
			
		||||
        for (ShoppingCartItem i : items) {
 | 
			
		||||
            if (i.getArticleId() == article.id) {
 | 
			
		||||
                i.setAmount(quantity);
 | 
			
		||||
                found = true;
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        if (!found) {
 | 
			
		||||
            items.add(new ShoppingCartItem(quantity, article));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        items.removeIf(i -> i.getAmount() == 0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static class ShoppingCartItem {
 | 
			
		||||
        private int amount;
 | 
			
		||||
        private final long articleId;
 | 
			
		||||
 | 
			
		||||
@ -60,5 +83,9 @@ public class ShoppingCart {
 | 
			
		||||
        public long getArticleId() {
 | 
			
		||||
            return articleId;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void setAmount(Integer amount) {
 | 
			
		||||
            this.amount = amount;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,7 +0,0 @@
 | 
			
		||||
CREATE TABLE "customers" (
 | 
			
		||||
	"id"	INTEGER PRIMARY KEY AUTOINCREMENT,
 | 
			
		||||
	"lastname"	TEXT,
 | 
			
		||||
	"firstname"	TEXT,
 | 
			
		||||
	"username"	TEXT,
 | 
			
		||||
	"password"	TEXT
 | 
			
		||||
);
 | 
			
		||||
@ -31,91 +31,31 @@
 | 
			
		||||
                <th>Menge</th>
 | 
			
		||||
                <th></th>
 | 
			
		||||
            </tr>
 | 
			
		||||
            <tr>
 | 
			
		||||
                <td><a th:href="@{/shop/articles/4151}"><img th:src="@{/img/product-1.jpg}" class="s"/><a/></td>
 | 
			
		||||
                <td><a th:href="@{/shop/articles/4151}">Kamera<a/></td>
 | 
			
		||||
                <td>100,50 EUR</td>
 | 
			
		||||
                <td>
 | 
			
		||||
                    <select size="1">
 | 
			
		||||
                        <option value="1" selected>1</option>
 | 
			
		||||
                        <option value="2">2</option>
 | 
			
		||||
                        <option value="3">3</option>
 | 
			
		||||
                        <option value="4">4</option>
 | 
			
		||||
                        <option value="5">5</option>
 | 
			
		||||
                    </select>
 | 
			
		||||
                </td>
 | 
			
		||||
                <td>
 | 
			
		||||
                    <button class="small">Entfernen</button>
 | 
			
		||||
                </td>
 | 
			
		||||
            </tr>
 | 
			
		||||
            <tr>
 | 
			
		||||
                <td><a th:href="@{/shop/articles/4151}"><img th:src="@{/img/product-2.jpg}" class="s"/><a/></td>
 | 
			
		||||
                <td><a th:href="@{/shop/articles/4151}">Earbuds<a/></td>
 | 
			
		||||
                <td>63,95 EUR</td>
 | 
			
		||||
                <td>
 | 
			
		||||
                    <select size="1">
 | 
			
		||||
                        <option value="1" selected>1</option>
 | 
			
		||||
                        <option value="2">2</option>
 | 
			
		||||
                        <option value="3">3</option>
 | 
			
		||||
                        <option value="4">4</option>
 | 
			
		||||
                        <option value="5">5</option>
 | 
			
		||||
                    </select>
 | 
			
		||||
                </td>
 | 
			
		||||
                <td>
 | 
			
		||||
                    <button>Entfernen</button>
 | 
			
		||||
                </td>
 | 
			
		||||
            </tr>
 | 
			
		||||
            <tr>
 | 
			
		||||
                <td><a th:href="@{/shop/articles/4151}"><img th:src="@{/img/product-3.jpg}" class="s"/><a/></td>
 | 
			
		||||
                <td><a th:href="@{/shop/articles/4151}">USB-Magic Light<a/></td>
 | 
			
		||||
                <td>11,90 EUR</td>
 | 
			
		||||
                <td>
 | 
			
		||||
                    <select size="1">
 | 
			
		||||
                        <option value="1">1</option>
 | 
			
		||||
                        <option value="2" selected>2</option>
 | 
			
		||||
                        <option value="3">3</option>
 | 
			
		||||
                        <option value="4">4</option>
 | 
			
		||||
                        <option value="5">5</option>
 | 
			
		||||
                    </select>
 | 
			
		||||
                </td>
 | 
			
		||||
                <td>
 | 
			
		||||
                    <button>Entfernen</button>
 | 
			
		||||
                </td>
 | 
			
		||||
            </tr>
 | 
			
		||||
            <tr>
 | 
			
		||||
                <td><a th:href="@{/shop/articles/4151}"><img th:src="@{/img/product-4.jpg}" class="s"/><a/></td>
 | 
			
		||||
                <td><a th:href="@{/shop/articles/4151}">3D Magic Stativ<a/></td>
 | 
			
		||||
                <td>15,99 EUR</td>
 | 
			
		||||
                <td>
 | 
			
		||||
                    <select size="1">
 | 
			
		||||
                        <option value="1">1</option>
 | 
			
		||||
                        <option value="2">2</option>
 | 
			
		||||
                        <option value="3">3</option>
 | 
			
		||||
                        <option value="4">4</option>
 | 
			
		||||
                        <option value="5" selected>5</option>
 | 
			
		||||
                    </select>
 | 
			
		||||
                </td>
 | 
			
		||||
                <td>
 | 
			
		||||
                    <button>Entfernen</button>
 | 
			
		||||
                </td>
 | 
			
		||||
            </tr>
 | 
			
		||||
            <tr>
 | 
			
		||||
                <td><a th:href="@{/shop/articles/4151}"><img th:src="@{/img/product-5.jpg}" class="s"/><a/></td>
 | 
			
		||||
                <td><a th:href="@{/shop/articles/4151}">Ersatzfernbedinung<a/></td>
 | 
			
		||||
                <td>7,95 EUR</td>
 | 
			
		||||
                <td>
 | 
			
		||||
                    <select size="1">
 | 
			
		||||
                        <option value="1" selected>1</option>
 | 
			
		||||
                        <option value="2">2</option>
 | 
			
		||||
                        <option value="3">3</option>
 | 
			
		||||
                        <option value="4">4</option>
 | 
			
		||||
                        <option value="5">5</option>
 | 
			
		||||
                    </select>
 | 
			
		||||
                </td>
 | 
			
		||||
                <td>
 | 
			
		||||
                    <button>Entfernen</button>
 | 
			
		||||
                </td>
 | 
			
		||||
            </tr>
 | 
			
		||||
            <th:block th:each="item : ${checkoutItems}">
 | 
			
		||||
                <tr>
 | 
			
		||||
                    <td><a th:href="@{/shop/articles/{id}(id = ${item.article.id})}"><img
 | 
			
		||||
                            th:src="@{/shop/articles/${item.article.id}/image.jpg}" class="s"/></a></td>
 | 
			
		||||
                    <td><a th:href="@{/shop/articles/{id}(id = ${item.article.id})}"
 | 
			
		||||
                           th:text="${item.article.title}"></a></td>
 | 
			
		||||
                    <td><span th:text="${#numbers.formatDecimal(item.total, 1, 'POINT', 2, 'COMMA')}"></span> EUR</td>
 | 
			
		||||
                    <td>
 | 
			
		||||
                        <form method="POST" th:action="@{/shop/articles/{id}(id = ${item.article.id})}">
 | 
			
		||||
                            <input type="hidden" name="fastcheckout" value="true"/>
 | 
			
		||||
                            <input type="hidden" name="set_amount" value="true"/>
 | 
			
		||||
                            <select name="quantity" size="1">
 | 
			
		||||
                                <option th:value="${item.amount}" th:text="${item.amount}" selected></option>
 | 
			
		||||
                                <option value="0">Entfernen</option>
 | 
			
		||||
                                <option value="1">1</option>
 | 
			
		||||
                                <option value="2">2</option>
 | 
			
		||||
                                <option value="3">3</option>
 | 
			
		||||
                                <option value="4">4</option>
 | 
			
		||||
                                <option value="5">5</option>
 | 
			
		||||
                            </select>
 | 
			
		||||
                            <button class="small">Ändern</button>
 | 
			
		||||
                        </form>
 | 
			
		||||
                    </td>
 | 
			
		||||
                </tr>
 | 
			
		||||
                <th:block>
 | 
			
		||||
        </table>
 | 
			
		||||
    </div>
 | 
			
		||||
    <form method="POST" th:action="@{/shop/checkoutFinish}" style="min-width: 30em; max-width: 45em;">
 | 
			
		||||
@ -151,23 +91,26 @@ Musterstraße 42
 | 
			
		||||
                <table>
 | 
			
		||||
                    <tr>
 | 
			
		||||
                        <th>Artikel (Netto)</th>
 | 
			
		||||
                        <th>200,29 EUR</th>
 | 
			
		||||
                    </tr>
 | 
			
		||||
                    <tr th:if="${user}">
 | 
			
		||||
                        <th>Bonuspunkte</th>
 | 
			
		||||
                        <th>-5,00 EUR</th>
 | 
			
		||||
                    </tr>
 | 
			
		||||
                    <tr>
 | 
			
		||||
                        <th>Umsatzsteuer (19%)</th>
 | 
			
		||||
                        <th>35,00 EUR</th>
 | 
			
		||||
                    </tr>
 | 
			
		||||
                    <tr>
 | 
			
		||||
                        <th>Umsatzsteuer (7%)</th>
 | 
			
		||||
                        <th>2,50 EUR</th>
 | 
			
		||||
                        <th><span
 | 
			
		||||
                                th:text="${#numbers.formatDecimal(checkoutTotals.net, 1, 'POINT', 2, 'COMMA')}"></span>
 | 
			
		||||
                            EUR
 | 
			
		||||
                        </th>
 | 
			
		||||
                    </tr>
 | 
			
		||||
                    <th:block th:each="item : ${checkoutTotals.vatAmounts.entrySet()}">
 | 
			
		||||
                        <tr>
 | 
			
		||||
                            <th>Umsatzsteuer (<span th:text="${item.getKey()}"></span>%)</th>
 | 
			
		||||
                            <th><span
 | 
			
		||||
                                    th:text="${#numbers.formatDecimal(item.getValue(), 1, 'POINT', 2, 'COMMA')}"></span>
 | 
			
		||||
                                EUR
 | 
			
		||||
                            </th>
 | 
			
		||||
                        </tr>
 | 
			
		||||
                    </th:block>
 | 
			
		||||
                    <tr class="secondary">
 | 
			
		||||
                        <th>Gesamt:</th>
 | 
			
		||||
                        <th>240,79 EUR</th>
 | 
			
		||||
                        <th><span
 | 
			
		||||
                                th:text="${#numbers.formatDecimal(checkoutTotals.total, 1, 'POINT', 2, 'COMMA')}"></span>
 | 
			
		||||
                            EUR
 | 
			
		||||
                        </th>
 | 
			
		||||
                    </tr>
 | 
			
		||||
                    <tr th:if="${user}" class="secondary">
 | 
			
		||||
                        <th colspan="2" class=" no-padding"></th>
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user