Implement CreateCustomerOrderAction; Not implemented: correct booking and WarehouseBooking fetching...

Puhh, that was a struggle to get working. Damn JPA Shit
This commit is contained in:
CodeSteak 2020-05-05 22:56:12 +02:00 committed by localhorst
parent d2bf6e8c52
commit 2ec3ad32ea
24 changed files with 526 additions and 53 deletions

View File

@ -1,9 +1,9 @@
/* password is 123 */
INSERT INTO users ("created", "email", "password_hash", "gets_ads", "is_active", "is_employee", "isb2b")
VALUES (datetime('now','localtime') ||'.0', "emp@ecom", "$2a$10$zFiqcePBmXHErD86vkI.vO1dnX20ezoVSM8xjGi59nktXYQv0o.fK", "0", "1", "1", "0");
INSERT INTO users ("created", "email", "password_hash", "is_active", "is_employee")
VALUES (datetime('now','localtime') ||'.0', "emp@ecom", "$2a$10$zFiqcePBmXHErD86vkI.vO1dnX20ezoVSM8xjGi59nktXYQv0o.fK", "1", "1");
INSERT INTO users ("created", "email", "password_hash", "gets_ads", "is_active", "is_employee", "isb2b")
VALUES (datetime('now','localtime') ||'.0', "user@ecom", "$2a$10$zFiqcePBmXHErD86vkI.vO1dnX20ezoVSM8xjGi59nktXYQv0o.fK", "1", "1", "0", "0");
INSERT INTO users ("created", "email", "password_hash", "is_active", "is_employee")
VALUES (datetime('now','localtime') ||'.0', "user@ecom", "$2a$10$zFiqcePBmXHErD86vkI.vO1dnX20ezoVSM8xjGi59nktXYQv0o.fK", "1", "0");
INSERT INTO users ("created", "email", "password_hash", "gets_ads", "is_active", "is_employee", "isb2b")
VALUES (datetime('now','localtime') ||'.0', "blocked@ecom", "$2a$10$zFiqcePBmXHErD86vkI.vO1dnX20ezoVSM8xjGi59nktXYQv0o.fK", "1", "0", "0", "0");
INSERT INTO users ("created", "email", "password_hash", "is_active", "is_employee")
VALUES (datetime('now','localtime') ||'.0', "blocked@ecom", "$2a$10$zFiqcePBmXHErD86vkI.vO1dnX20ezoVSM8xjGi59nktXYQv0o.fK", "0", "0");

View File

@ -0,0 +1,30 @@
package org.hso.ecommerce.action.booking;
import org.hso.ecommerce.entities.booking.Booking;
import org.hso.ecommerce.entities.booking.BookingAccountEntry;
import org.hso.ecommerce.entities.booking.BookingReason;
public class CreateBookingAction {
private Booking booking;
public CreateBookingAction(BookingAccountEntry source, BookingAccountEntry destination, BookingReason reason, int amountCent) {
booking = new Booking();
booking.reason = reason;
booking.amountCent = amountCent;
assert source != null || destination != null;
if (source != null) {
booking.source = source.copyAddAmount(-amountCent);
}
if (destination != null) {
booking.destination = destination.copyAddAmount(amountCent);
}
}
public Booking finish() {
return booking;
}
}

View File

@ -0,0 +1,177 @@
package org.hso.ecommerce.action.shop;
import org.hso.ecommerce.action.booking.CreateBookingAction;
import org.hso.ecommerce.entities.booking.*;
import org.hso.ecommerce.entities.shop.Address;
import org.hso.ecommerce.entities.shop.Article;
import org.hso.ecommerce.entities.shop.CustomerOrder;
import org.hso.ecommerce.entities.shop.CustomerOrderPosition;
import org.hso.ecommerce.entities.user.User;
import org.hso.ecommerce.entities.warehouse.WarehouseBooking;
import org.hso.ecommerce.entities.warehouse.WarehouseBookingPosition;
import org.hso.ecommerce.entities.warehouse.WarehouseBookingPositionSlotEntry;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
public class CreateOrderAction {
private User user;
Address destination;
private int expectedTotalGrossCent;
private int totalNetCent;
private int totalVatCent;
private PaymentMethod method;
private BookingAccountEntry latestUserBooking;
private BookingAccountEntry latestVatBooking;
private BookingAccountEntry latestMainBooking;
private List<OrderItem> orderItems = new ArrayList<>();
public CreateOrderAction(
User user,
int expectedTotalGrossCent,
Address destination,
PaymentMethod method,
BookingAccountEntry latestUserBooking,
BookingAccountEntry latestVatBooking,
BookingAccountEntry latestMainBooking
) {
this.user = user;
this.expectedTotalGrossCent = expectedTotalGrossCent;
this.destination = destination;
this.method = method;
this.latestUserBooking = latestUserBooking;
assert latestUserBooking.userAccount.id == user.id;
this.latestVatBooking = latestVatBooking;
assert latestVatBooking.isVATAccount;
this.latestMainBooking = latestMainBooking;
assert latestMainBooking.isMainAccount;
}
public void addArticle(Article article, int quantity, List<WarehouseBookingPositionSlotEntry> availableSlots) {
for (WarehouseBookingPositionSlotEntry slot : availableSlots) {
assert slot.article.id == article.id;
}
orderItems.add(new OrderItem(article, availableSlots, quantity));
totalNetCent += article.shopPricePerUnitNetCent * quantity;
totalVatCent += article.getVat() * quantity;
}
public Result finish() {
CustomerOrder order = createOrder();
CustomerPayment payment = createPayment();
List<Booking> bookingList = new ArrayList<>();
bookingList.add(new CreateBookingAction(latestUserBooking, latestMainBooking, new BookingReason(order), order.totalGrossCent).finish());
bookingList.add(new CreateBookingAction(null, latestUserBooking, new BookingReason(payment), order.totalGrossCent).finish());
bookingList.add(new CreateBookingAction(latestMainBooking, latestVatBooking, new BookingReason(order), order.totalVatCent).finish());
WarehouseBooking warehouseBooking = createWarehouseBooking(order);
return new Result(
order,
warehouseBooking,
bookingList
);
}
private WarehouseBooking createWarehouseBooking(CustomerOrder order) {
WarehouseBooking booking = new WarehouseBooking();
booking.created = new Timestamp(new Date().getTime());
booking.reason = new BookingReason(order);
for (OrderItem item : orderItems) {
int needed = item.quantity;
for (WarehouseBookingPositionSlotEntry slot : item.availableSlots) {
int remove = Math.min(slot.newSumSlot, needed);
needed -= remove;
WarehouseBookingPosition bookingPosition = new WarehouseBookingPosition();
bookingPosition.article = item.article;
bookingPosition.amount = -remove;
bookingPosition.slotEntry = slot.copyAddAmount(-remove);
bookingPosition.booking = booking;
booking.positions.add(bookingPosition);
if (needed == 0) {
break;
}
}
}
return booking;
}
private CustomerPayment createPayment() {
CustomerPayment payment = new CustomerPayment();
payment.amountCent = totalNetCent + totalVatCent;
payment.payment = method;
return payment;
}
private CustomerOrder createOrder() {
assert totalNetCent + totalVatCent == expectedTotalGrossCent;
CustomerOrder customerOrder = new CustomerOrder();
customerOrder.customer = user;
customerOrder.destination = destination;
for (OrderItem item : orderItems) {
CustomerOrderPosition position = new CustomerOrderPosition();
position.article = item.article;
position.pricePerUnit = item.article.shopPricePerUnitNetCent;
position.quantity = item.quantity;
position.order = customerOrder;
customerOrder.positions.add(position);
}
customerOrder.created = new Timestamp(new Date().getTime());
customerOrder.totalNetCent = totalNetCent;
customerOrder.totalVatCent = totalVatCent;
customerOrder.totalGrossCent = totalNetCent + totalVatCent;
return customerOrder;
}
public static class Result {
public final CustomerOrder customerOrder;
public final WarehouseBooking warehouseBooking;
public final List<Booking> bookings;
Result(CustomerOrder customerOrder, WarehouseBooking warehouseBooking, List<Booking> bookings) {
this.customerOrder = customerOrder;
this.warehouseBooking = warehouseBooking;
this.bookings = bookings;
}
}
private static class OrderItem {
List<WarehouseBookingPositionSlotEntry> availableSlots;
int quantity;
Article article;
public OrderItem(Article article, List<WarehouseBookingPositionSlotEntry> availableSlots, int quantity) {
this.article = article;
this.availableSlots = availableSlots;
this.quantity = quantity;
}
}
}

View File

@ -0,0 +1,11 @@
package org.hso.ecommerce.action.shop;
import org.hso.ecommerce.entities.shop.CustomerOrder;
public class EnableTrackingAction {
public static void addTrackingInfo(CustomerOrder customerOrder) {
// TODO:
customerOrder.trackingId = "555-NASE";
}
}

View File

@ -1,7 +0,0 @@
package org.hso.ecommerce.action.somepackage;
public class DemoAction {
// TODO: remove me.
// mksubpackage
}

View File

@ -1,14 +1,23 @@
package org.hso.ecommerce.controller.shop;
import org.hso.ecommerce.action.shop.CreateOrderAction;
import org.hso.ecommerce.action.shop.EnableTrackingAction;
import org.hso.ecommerce.entities.booking.BookingAccountEntry;
import org.hso.ecommerce.entities.booking.PaymentMethod;
import org.hso.ecommerce.entities.shop.Address;
import org.hso.ecommerce.entities.shop.Article;
import org.hso.ecommerce.entities.shop.ShoppingCart;
import org.hso.ecommerce.entities.user.User;
import org.hso.ecommerce.repos.booking.BookingAccountEntryRepository;
import org.hso.ecommerce.repos.booking.BookingRepository;
import org.hso.ecommerce.repos.shop.ArticleRepository;
import org.hso.ecommerce.repos.shop.CustomerOderRepository;
import org.hso.ecommerce.repos.user.UserRepository;
import org.hso.ecommerce.repos.warehouse.WarehouseBookingPositionSlotEntryRepository;
import org.hso.ecommerce.repos.warehouse.WarehouseBookingRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
@ -19,9 +28,27 @@ import java.util.TreeMap;
@RequestMapping("/shop/")
public class ShopCheckoutController {
@Autowired
private final UserRepository userRepository = null;
@Autowired
private final ArticleRepository articleRepository = null;
@Autowired
private final BookingAccountEntryRepository bookingEntryRepository = null;
@Autowired
private final BookingRepository bookingRepository = null;
@Autowired
private final WarehouseBookingRepository warehouseBookingRepository = null;
@Autowired
private final CustomerOderRepository customerOderRepository = null;
@Autowired
private final WarehouseBookingPositionSlotEntryRepository wbeseRepo = null;
@GetMapping("/checkout")
public String shopCheckout(HttpSession session,
HttpServletRequest request,
@ -69,7 +96,43 @@ public class ShopCheckoutController {
}
@PostMapping("/checkoutFinish")
public String shopCheckoutFinish() {
public String shopCheckoutFinish(
@RequestAttribute(value = "user") User user,
@RequestAttribute(value = "shoppingCart") ShoppingCart shoppingCart,
@RequestParam("address") String address,
@RequestParam("cardnumber") String cardnumber,
@RequestParam("shopping_cart_revision") Integer cartRevision,
@RequestParam("expected_total") Integer expectedPrice
) {
// Must be refetched for persitence.
user = userRepository.findById(user.id).get();
CreateOrderAction action = new CreateOrderAction(
user,
expectedPrice,
Address.fromString(address),
PaymentMethod.fromCreditCarNumber(cardnumber),
bookingEntryRepository.getByUser(user).orElse(BookingAccountEntry.newUser(user)),
bookingEntryRepository.getByVat().orElse(BookingAccountEntry.newVat()),
bookingEntryRepository.getByMain().orElse(BookingAccountEntry.newMain())
);
for (ShoppingCart.ShoppingCartItem item : shoppingCart.getItems()) {
Article article = articleRepository.findById(item.getArticleId()).get();
action.addArticle(article, item.getAmount(), wbeseRepo.getByArticle(article));
}
CreateOrderAction.Result result = action.finish();
EnableTrackingAction.addTrackingInfo(result.customerOrder);
customerOderRepository.save(result.customerOrder);
bookingRepository.saveAll(result.bookings);
warehouseBookingRepository.save(result.warehouseBooking);
shoppingCart.clear();
return "shop/checkoutFinish";
}

View File

@ -14,12 +14,12 @@ public class Booking {
// always >= 0
public int amountCent;
@ManyToOne(optional = true)
@ManyToOne(optional = true, cascade = CascadeType.ALL)
public BookingAccountEntry source;
@ManyToOne(optional = true)
@ManyToOne(optional = true, cascade = CascadeType.ALL)
public BookingAccountEntry destination;
@OneToOne(optional = false)
@OneToOne(optional = false, cascade = CascadeType.ALL)
public BookingReason reason;
}

View File

@ -16,13 +16,49 @@ public class BookingAccountEntry {
public int newSumCent;
@ManyToOne(optional = true)
@ManyToOne(optional = true, cascade = CascadeType.ALL)
public User userAccount;
@ManyToOne(optional = true)
@ManyToOne(optional = true, cascade = CascadeType.ALL)
public Supplier supplierAccount;
public boolean isMainAccount;
public boolean isVATAccount;
public BookingAccountEntry copyAddAmount(int amountCent) {
BookingAccountEntry e = new BookingAccountEntry();
e.userAccount = userAccount;
e.supplierAccount = supplierAccount;
e.isMainAccount = isMainAccount;
e.isVATAccount = isVATAccount;
e.newSumCent = newSumCent + amountCent;
return e;
}
public static BookingAccountEntry newUser(User user) {
BookingAccountEntry e = new BookingAccountEntry();
e.userAccount = user;
e.newSumCent = 0;
return e;
}
public static BookingAccountEntry newMain() {
BookingAccountEntry e = new BookingAccountEntry();
e.isMainAccount = true;
e.newSumCent = 0;
return e;
}
public static BookingAccountEntry newVat() {
BookingAccountEntry e = new BookingAccountEntry();
e.isVATAccount = true;
e.newSumCent = 0;
return e;
}
}

View File

@ -22,9 +22,22 @@ public class BookingReason {
@ManyToOne(optional = true)
public CustomerOrder customerOrder;
@ManyToOne(optional = true)
@OneToOne(optional = true, cascade = CascadeType.ALL)
public CustomerPayment customerPayment;
@ManyToOne(optional = true)
public SupplierOrder supplierOrder;
public BookingReason() {
}
;
public BookingReason(CustomerOrder order) {
this.customerOrder = order;
}
public BookingReason(CustomerPayment customerPayment) {
this.customerPayment = customerPayment;
}
}

View File

@ -7,4 +7,11 @@ import javax.validation.constraints.NotNull;
public class PaymentMethod {
@NotNull
public String creditCardNumber;
public static PaymentMethod fromCreditCarNumber(String cardnumber) {
PaymentMethod m = new PaymentMethod();
m.creditCardNumber = cardnumber;
return m;
}
}

View File

@ -4,7 +4,24 @@ import javax.persistence.Embeddable;
@Embeddable
public class Address {
public String name;
public String addressString;
public String name = "";
public String addressString = "";
public String country = "DE";
@Override
public String toString() {
return name + "\n" + addressString;
}
public static Address fromString(String addr) {
Address a = new Address();
String[] arr = addr.split("\n", 2);
a.name = arr[0];
if (arr.length > 1) {
a.addressString = arr[1];
}
return a;
}
}

View File

@ -24,7 +24,7 @@ public class CustomerOrder {
@OneToMany(
targetEntity = CustomerOrderPosition.class,
mappedBy = "order"
mappedBy = "order", cascade = CascadeType.ALL
)
public List<CustomerOrderPosition> positions = new ArrayList<>();

View File

@ -6,12 +6,18 @@ import java.util.List;
// Not a db entity. Just for session storage
public class ShoppingCart {
private final static int MAX_ITEMS = 10;
private int revision;
private ArrayList<ShoppingCartItem> items;
public ShoppingCart() {
revision = (int) Math.round(Math.random() * 0xFFFF);
clear();
}
public void clear() {
items = new ArrayList<>();
revision = (int) Math.round(Math.random() * 0xFFFF);
}
public List<ShoppingCartItem> getItems() {
@ -60,7 +66,7 @@ public class ShoppingCart {
items.add(new ShoppingCartItem(quantity, article));
}
items.removeIf(i -> i.getAmount() == 0);
items.removeIf(i -> i.getAmount() <= 0);
}
public static class ShoppingCartItem {
@ -78,6 +84,9 @@ public class ShoppingCart {
public void addAmount(int amount) {
this.amount += amount;
if (this.amount > MAX_ITEMS) {
this.amount = MAX_ITEMS;
}
}
public long getArticleId() {
@ -86,6 +95,9 @@ public class ShoppingCart {
public void setAmount(Integer amount) {
this.amount = amount;
if (this.amount > MAX_ITEMS) {
this.amount = MAX_ITEMS;
}
}
}
}

View File

@ -30,10 +30,10 @@ public class User {
public boolean isEmployee;
@Embedded
private Address defaultDeliveryAddress;
public Address defaultDeliveryAddress;
@Embedded
private PaymentMethod defaultPayment;
public PaymentMethod defaultPayment;
public long getId() {
return id;

View File

@ -1,5 +1,7 @@
package org.hso.ecommerce.entities.warehouse;
import org.hso.ecommerce.entities.booking.BookingReason;
import javax.persistence.*;
import javax.validation.constraints.NotNull;
import java.util.ArrayList;
@ -21,7 +23,10 @@ public class WarehouseBooking {
public boolean isDone;
@OneToMany(
mappedBy = "booking"
mappedBy = "booking", cascade = CascadeType.ALL
)
public List<WarehouseBookingPosition> positions = new ArrayList<>();
@OneToOne(optional = false, cascade = CascadeType.ALL)
public BookingReason reason;
}

View File

@ -23,10 +23,6 @@ public class WarehouseBookingPosition {
public int amount; // positive or negative
@ManyToOne(optional = true)
public WarehouseBookingPositionSlotEntry source;
@ManyToOne(optional = true)
public WarehouseBookingPositionSlotEntry destination;
@ManyToOne(optional = true, cascade = CascadeType.ALL)
public WarehouseBookingPositionSlotEntry slotEntry;
}

View File

@ -16,8 +16,23 @@ public class WarehouseBookingPositionSlotEntry {
@ManyToOne
public Article article;
public int newSumArticles;
public int newSumWarehousePosition;
// Can;t do, does not work when created in action.
//public int newSumArticles;
public int newSumSlot;
public int slot;
public WarehouseBookingPositionSlotEntry copyAddAmount(int amount) {
WarehouseBookingPositionSlotEntry e = new WarehouseBookingPositionSlotEntry();
e.article = article;
e.slot = slot;
e.newSumSlot = newSumSlot + amount;
assert e.article.warehouseUnitsPerSlot >= e.newSumSlot;
assert e.newSumSlot >= 0;
return e;
}
}

View File

@ -23,4 +23,11 @@ public class WarehouseBookingReason {
public CustomerOrder customerOrder;
public boolean isManuel;
public WarehouseBookingReason() {
}
public WarehouseBookingReason(CustomerOrder order) {
this.customerOrder = order;
}
}

View File

@ -0,0 +1,26 @@
package org.hso.ecommerce.repos.booking;
import org.hso.ecommerce.entities.booking.BookingAccountEntry;
import org.hso.ecommerce.entities.user.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;
import java.util.Optional;
@Repository
public interface BookingAccountEntryRepository extends JpaRepository<BookingAccountEntry, Long> {
@Query("SELECT e FROM BookingAccountEntry e WHERE e.userAccount = :user ORDER BY e.id DESC")
Optional<BookingAccountEntry> getByUser(User user);
@Query("SELECT e FROM BookingAccountEntry e WHERE e.isMainAccount = 1 ORDER BY e.id DESC")
Optional<BookingAccountEntry> getByMain();
@Query("SELECT e FROM BookingAccountEntry e WHERE e.isVATAccount = 1 ORDER BY e.id DESC")
Optional<BookingAccountEntry> getByVat();
}

View File

@ -0,0 +1,12 @@
package org.hso.ecommerce.repos.booking;
import org.hso.ecommerce.entities.booking.Booking;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface BookingRepository extends JpaRepository<Booking, Long> {
}

View File

@ -0,0 +1,11 @@
package org.hso.ecommerce.repos.shop;
import org.hso.ecommerce.entities.shop.CustomerOrder;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface CustomerOderRepository extends JpaRepository<CustomerOrder, Long> {
}

View File

@ -0,0 +1,18 @@
package org.hso.ecommerce.repos.warehouse;
import org.hso.ecommerce.entities.shop.Article;
import org.hso.ecommerce.entities.warehouse.WarehouseBookingPositionSlotEntry;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface WarehouseBookingPositionSlotEntryRepository extends JpaRepository<WarehouseBookingPositionSlotEntry, Long> {
// TODO this is wrong. revisit.
@Query("SELECT e FROM WarehouseBookingPositionSlotEntry e WHERE e.article = :article ORDER BY e.id DESC")
List<WarehouseBookingPositionSlotEntry> getByArticle(Article article);
}

View File

@ -0,0 +1,11 @@
package org.hso.ecommerce.repos.warehouse;
import org.hso.ecommerce.entities.warehouse.WarehouseBooking;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface WarehouseBookingRepository extends JpaRepository<WarehouseBooking, Long> {
}

View File

@ -21,7 +21,17 @@
</div>
<nav></nav>
</div>
<main class="content-width sidebar-layout" style="min-height: 100vh;">
<main th:if="${checkoutItems.size() == 0}">
<div class="detailflex m">
<h2> Noch keine Artikel im Warenkorb. </h2>
<p>
<img th:src="@{/img/undraw_successful_purchase_secondary.svg}"/>
</p>
<a class="button" th:href="@{/}"> Weiter shoppen </a>
</div>
</main>
<main th:if="${checkoutItems.size() > 0}" class="content-width sidebar-layout" style="min-height: 100vh;">
<div style="max-width: 45em; width: 100%;">
<table>
<tr>
@ -37,7 +47,9 @@
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><span
th:text="${#numbers.formatDecimal(item.article.getPriceGross(), 1, 'POINT', 2, 'COMMA')}"></span>
EUR <b>x</b></td>
<td>
<form method="POST" th:action="@{/shop/articles/{id}(id = ${item.article.id})}">
<input type="hidden" name="fastcheckout" value="true"/>
@ -45,11 +57,9 @@
<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>
<option th:each="quantity : ${#numbers.sequence(1,10)}"
th:value="${quantity}"
th:text="${quantity}"></option>
</select>
<button class="small">Ändern</button>
</form>
@ -64,11 +74,16 @@
<h1>Checkout</h1>
</div>
<div th:if="${user}">
<input type="hidden" name="shopping_cart_revision" th:value="${shoppingCart.getRevision()}"/>
<input type="hidden" name="expected_total" th:value="${checkoutTotals.total}"/>
<h2>Lieferadresse:</h2>
<textarea rows="5" class="full-width" type="text" name="address"
placeholder="Optional: Zusatz&#10;Optional: Unternehmen&#10;Straße Hausnummer&#10;Postleitzeit Ort&#10;Land">
placeholder="Name&#10;Optional: Zusatz&#10;Optional: Unternehmen&#10;Straße Hausnummer&#10;Postleitzeit Ort&#10;Land"
th:text="${user.defaultDeliveryAddress != null ? user.defaultDeliveryAddress.toString() : ''}"
required>
Max Mustermann
Musterstraße 42
Musterstraße 4
42424 Mustertal
</textarea>
</div>
@ -78,12 +93,10 @@ Musterstraße 42
<input type="radio" name="type" value="priv" id="payment-card" required checked>
<label for="payment-card">Kartenzahlung</label> <br/>
<input class="full-width" type="text" id="cardnumber" name="cardnumber" placeholder="Kartennummer"
th:value="${user.defaultPayment != null ? user.defaultPayment.creditCardNumber : ''}"
pattern="[0-9]{6,16}"
required/>
</fieldset>
<fieldset>
<input class="" type="checkbox" id="bonus" name="bonus" checked/>
<label for="bonus"><h3>10 gesammelte Bonuspunkte verwenden</h3></label>
</fieldset>
</div>
<div>
<h2>Bestellübersicht</h2>