Update basics of order package to salespoint

This removes the calendar, as it currently conflicts with the salespoint
architecture.

Works on #38
This commit is contained in:
Mathis Kral 2023-11-19 13:00:21 +01:00 committed by Simon Bruder
parent 0c4286e198
commit a8a67a9626
Signed by: simon
GPG key ID: 8D3C82F9F309F8EC
10 changed files with 237 additions and 362 deletions

View file

@ -1,45 +1,50 @@
package catering.order; package catering.order;
import org.salespointframework.quantity.Quantity; import org.salespointframework.order.Cart;
import org.springframework.stereotype.Component;
import java.util.HashMap; import java.time.LocalDateTime;
import java.util.Map; import java.time.format.DateTimeFormatter;
public class CustomCart extends Cart {
private OrderType orderType;
private LocalDateTime start;
private LocalDateTime finish;
private final String formatterPattern;
@Component // Constructor
public class CustomCart { public CustomCart(OrderType orderType, LocalDateTime start, LocalDateTime finish) {
private CustomOrder.OrderType orderType; super();
private Map<String, Quantity> products; this.orderType = orderType;
this.start = start;
public CustomCart() { this.finish = finish;
this.orderType = CustomOrder.OrderType.SOMETHING_ELSE; this.formatterPattern = "dd.MM.yyy, HH:mm 'Uhr'";
this.products = new HashMap<>();
} }
public CustomOrder.OrderType getOrderType() { public OrderType getOrderType() {
return orderType; return orderType;
} }
public void setOrderType(CustomOrder.OrderType type) { public void setOrderType(OrderType orderType) {
this.orderType = type; this.orderType = orderType;
return;
} }
public Map<String, Quantity> getProucts() { public LocalDateTime getStart() {
return products; return start;
} }
public void addProduct(String product, int number) { public void setStart(LocalDateTime start) {
products.put(product, Quantity.of(number)); this.start = start;
} }
public boolean removeProduct(String product) { public LocalDateTime getFinish() {
return products.remove(product) != null; return finish;
} }
public void resetCart() { public void setFinish(LocalDateTime finish) {
orderType = CustomOrder.OrderType.SOMETHING_ELSE; this.finish = finish;
products = new HashMap<>(); }
public String getFormatterPattern() {
return formatterPattern;
} }
} }

View file

@ -1,43 +1,32 @@
package catering.order; package catering.order;
import com.querydsl.core.Tuple; import jakarta.persistence.Entity;
import org.aspectj.weaver.ast.Or; import org.salespointframework.order.Order;
import org.salespointframework.quantity.Quantity; import org.salespointframework.payment.Cash;
import org.salespointframework.useraccount.UserAccount;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;
/** @Entity
* This class is only used for the prototype to avoid using the bloated Salespoint API public class CustomOrder extends Order {
*/ private OrderType orderType = OrderType.SOMETHING_ELSE;
public class CustomOrder {
private int id;
private OrderType orderType;
private LocalDateTime start; private LocalDateTime start;
private LocalDateTime finish; private LocalDateTime finish;
private Map<String, Quantity> products; private boolean invoiceAvailable = false;
private boolean invoiceAvailable; private String formatterPattern = "dd.MM.yyy, HH:mm 'Uhr'";
private double totalCost; // this is in
private DateTimeFormatter formatter;
public CustomOrder(OrderType orderType, LocalDateTime start, LocalDateTime finish, Map<String, Quantity> products, boolean invoiceAvailable, double totalCost) { // Constructor
this.id = (int) (Math.random() * Integer.MAX_VALUE); public CustomOrder(UserAccount.UserAccountIdentifier identifier, CustomCart cart) {
this.orderType = orderType; super(identifier, Cash.CASH);
this.start = start; this.orderType = cart.getOrderType();
this.finish = finish; this.start = cart.getStart();
this.products = products; this.finish = cart.getFinish();
this.invoiceAvailable = invoiceAvailable; this.formatterPattern = cart.getFormatterPattern();
this.totalCost = totalCost;
this.formatter = DateTimeFormatter.ofPattern("dd.MM.yyy, HH:mm 'Uhr'");
} }
public int getId() { public CustomOrder() {} // TODO: find out, why this is mandatory
return id;
}
public OrderType getOrderType() { public OrderType getOrderType() {
return orderType; return orderType;
@ -48,7 +37,11 @@ public class CustomOrder {
} }
public String getFormattedStart() { public String getFormattedStart() {
return start.format(formatter); return start.format(DateTimeFormatter.ofPattern(formatterPattern));
}
public void setStart(LocalDateTime start) {
this.start = start;
} }
public LocalDateTime getFinish() { public LocalDateTime getFinish() {
@ -56,31 +49,18 @@ public class CustomOrder {
} }
public String getFormattedFinish() { public String getFormattedFinish() {
return finish.format(formatter); return finish.format(DateTimeFormatter.ofPattern(formatterPattern));
} }
public Map<String, Quantity> getProducts() { public void setFinish(LocalDateTime finish) {
return products; this.finish = finish;
} }
public Collection<String> getFormattedProducts() { public boolean isInvoiceAvailable() {
ArrayList<String> formattedProducts = new ArrayList<>();
getProducts().forEach((k, v) -> formattedProducts.add(k + ": " + v));
return formattedProducts;
}
public boolean invoiceAvailable() {
return invoiceAvailable; return invoiceAvailable;
} }
public double getTotalCost() { public void setInvoiceAvailable(boolean available) {
return totalCost; this.invoiceAvailable = available;
}
enum OrderType {
RENT_A_COOK,
EVENT_CATERING,
SUSHI_NIGHT,
SOMETHING_ELSE
} }
} }

View file

@ -1,76 +0,0 @@
package catering.order;
import org.salespointframework.core.DataInitializer;
import org.salespointframework.quantity.Quantity;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
@Component
public class CustomOrderDataInitializer implements DataInitializer {
private CustomOrderRepository orderRepository;
public CustomOrderDataInitializer(CustomOrderRepository orderRepository) {
this.orderRepository = orderRepository;
}
@Override
public void initialize() {
Map<String, Quantity> products = new HashMap<>();
products.put("Sake Maki", Quantity.of(100));
products.put("Sake Nigiri", Quantity.of(101));
orderRepository.addOrder(new CustomOrder(
CustomOrder.OrderType.SUSHI_NIGHT,
LocalDateTime.of(2023, 12, 5, 18, 0),
LocalDateTime.of(2023, 12, 5, 23, 0),
products,
false,
2000.0
));
products = new HashMap<>();
products.put("Koch", Quantity.of(3));
products.put("Wasser (still)", Quantity.of(101));
products.put("Käseplatte", Quantity.of(1000));
products.put("Wiener Würstchen", Quantity.of(150));
orderRepository.addOrder(new CustomOrder(
CustomOrder.OrderType.EVENT_CATERING,
LocalDateTime.of(2023, 10, 2, 11, 0),
LocalDateTime.of(2023, 10, 3, 8, 0),
products,
true,
10000.0
));
products = new HashMap<>();
products.put("Koch", Quantity.of(2));
products.put("Wiener Schnitzel (vegan)", Quantity.of(1000));
products.put("Wiener Würstchen", Quantity.of(150));
products.put("Weißwurst (vegan)", Quantity.of(300));
orderRepository.addOrder(new CustomOrder(
CustomOrder.OrderType.RENT_A_COOK,
LocalDateTime.of(2023, 12, 24, 11, 0),
LocalDateTime.of(2023, 12, 25, 14, 0),
products,
true,
4000.0
));
products = new HashMap<>();
products.put("Koch", Quantity.of(3));
products.put("Wasser (still)", Quantity.of(101));
products.put("Käseplatte", Quantity.of(1000));
products.put("Wiener Würstchen", Quantity.of(150));
orderRepository.addOrder(new CustomOrder(
CustomOrder.OrderType.EVENT_CATERING,
LocalDateTime.of(2023, 11, 20, 11, 0),
LocalDateTime.of(2023, 11, 21, 8, 0),
products,
true,
1001.0
));
}
}

View file

@ -1,47 +0,0 @@
package catering.order;
import org.springframework.stereotype.Component;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import java.util.stream.Collectors;
/**
* This class is only used for the prototype to avoid using the bloated Salespoint API
*/
@Component
public class CustomOrderRepository {
private Set<CustomOrder> orders;
public CustomOrderRepository() {
this.orders = new HashSet<>();
}
public boolean addOrder(CustomOrder order) {
return this.orders.add(order);
}
public boolean removeOrder(int orderID) {
for (CustomOrder order : orders) {
if (order.getId() == orderID) {
return this.orders.remove(order);
}
}
return false;
}
public Collection<CustomOrder> getOrders() {
return new ArrayList<>(this.orders);
}
// For Theo: returns all orders that happen on this day
public Collection<CustomOrder> getOrdersByDate(LocalDate date) {
return this.orders.stream().filter(order ->
(order.getStart().toLocalDate().isBefore(date) || order.getStart().toLocalDate().isEqual(date))
&& (order.getFinish().toLocalDate().isAfter(date) || order.getFinish().toLocalDate().isEqual(date))
).collect(Collectors.toList());
}
}

View file

@ -1,6 +1,18 @@
package catering.order; package catering.order;
import org.springframework.data.util.Streamable; import org.salespointframework.catalog.Product;
import org.salespointframework.inventory.UniqueInventory;
import org.salespointframework.inventory.UniqueInventoryItem;
import org.salespointframework.order.Cart;
import org.salespointframework.order.Order;
import org.salespointframework.order.OrderManagement;
import org.salespointframework.quantity.Quantity;
import org.salespointframework.time.Interval;
import org.salespointframework.useraccount.Role;
import org.salespointframework.useraccount.UserAccount;
import org.salespointframework.useraccount.web.LoggedIn;
import org.springframework.data.domain.Pageable;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.ui.Model; import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
@ -11,159 +23,158 @@ import java.time.temporal.ChronoUnit;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Comparator; import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.stream.Collectors;
@Controller @Controller
@PreAuthorize("isAuthenticated()")
@SessionAttributes("event")
public class OrderController { public class OrderController {
private final CustomOrderRepository orderRepository; private final OrderManagement<CustomOrder> orderManagement;
private final CustomCart cart; private final UniqueInventory<UniqueInventoryItem> inventory;
public OrderController(CustomOrderRepository orderRepository, CustomCart cart) { public OrderController(OrderManagement<CustomOrder> orderManagement, UniqueInventory<UniqueInventoryItem> inventory) {
this.orderRepository = orderRepository; this.orderManagement = orderManagement;
this.cart = cart; this.inventory = inventory;
} }
@GetMapping("/orders") @GetMapping("/myOrders")
public String orders(Model model) { @PreAuthorize("hasRole('CUSTOMER')")
model.addAttribute("orders", orderRepository.getOrders()); public String orders(Model model, @LoggedIn Optional<UserAccount> userAccount) {
model.addAttribute("total", orderRepository.getOrders().size()); List<CustomOrder> myOrders = orderManagement.findBy(userAccount.get()).stream().collect(Collectors.toList()); // to be changed
return "orders";
}
// For Theo: filters orders by day
@GetMapping("/orders/{day}")
public String orders(@PathVariable String day, Model model) {
// Obtains an instance of LocalDate from a text string such as 2007-12-03. (https://docs.oracle.com/javase/8/docs/api/java/time/LocalDate.html)
LocalDate date = LocalDate.parse(day);
Collection<CustomOrder> myOrders = orderRepository.getOrdersByDate(date);
model.addAttribute("orders", myOrders); model.addAttribute("orders", myOrders);
model.addAttribute("total", myOrders.size()); model.addAttribute("total", myOrders.size());
return "orders"; return "orders";
} }
@GetMapping("/allOrders")
@PreAuthorize("hasRole('ADMIN')")
public String orders(Model model) {
List<CustomOrder> myOrders = orderManagement.findAll(Pageable.unpaged()).stream().collect(Collectors.toList());
model.addAttribute("orders", myOrders);
model.addAttribute("total", myOrders.size());
return "orders";
}
// For Theo: filters orders by day
@GetMapping("/allOrders/{day}")
@PreAuthorize("hasRole('ADMIN')")
public String orders(@PathVariable String day, Model model) {
// Obtains an instance of LocalDate from a text string such as 2007-12-03. (https://docs.oracle.com/javase/8/docs/api/java/time/LocalDate.html)
LocalDate date = LocalDate.parse(day);
List<CustomOrder> myOrders = orderManagement.findAll(Pageable.unpaged()).stream().filter(
order ->
(order.getStart().toLocalDate().isBefore(date) || order.getStart().toLocalDate().isEqual(date))
&& (order.getFinish().toLocalDate().isAfter(date) || order.getFinish().toLocalDate().isEqual(date))
).collect(Collectors.toList());
model.addAttribute("orders", myOrders);
model.addAttribute("total", myOrders.size());
return "orders";
}
@ModelAttribute("event")
CustomCart initializeCart() {
return new CustomCart(OrderType.SOMETHING_ELSE, LocalDateTime.now(), LocalDateTime.now());
}
@GetMapping("/event") @GetMapping("/event")
public String event(Model model) { @PreAuthorize("hasRole('CUSTOMER')")
model.addAttribute("orderType", cart.getOrderType()); public String event(Model model, @ModelAttribute("event") CustomCart cart) {
model.addAttribute("items", cart.getProucts()); model.addAttribute("items", cart.stream().collect(Collectors.toList()));
model.addAttribute("productForm", new ProductForm()); model.addAttribute("totalPrice", cart.getPrice());
model.addAttribute("invItems", inventory.findAll().stream().collect(Collectors.toList()));
return "event"; return "event";
} }
@PostMapping("/orders/remove") @PostMapping("/allOrders/remove")
public String removeOrder(@RequestParam int orderID) { public String removeOrder(@RequestParam Order.OrderIdentifier orderID, @LoggedIn Optional<UserAccount> userAccount) {
orderRepository.removeOrder(orderID); return userAccount.map(account -> {
return "redirect:/orders"; if (account.hasRole(Role.of("ADMIN"))) {
CustomOrder myOrder = orderManagement.get(orderID).get(); // FIXME
orderManagement.cancelOrder(myOrder, "I have my own reasons.");
return "redirect:/allOrders";
}
return "redirect:/";
}).orElse("redirect:/");
} }
@PostMapping("/event/addProduct") @PostMapping("/event/addProduct")
public String addProduct(@ModelAttribute ProductForm productForm, Model model) { @PreAuthorize("hasRole('CUSTOMER')")
cart.addProduct(productForm.getProduct(), productForm.getNumber()); public String addProduct(@RequestParam("pid") Product product, @RequestParam("number") int number, @ModelAttribute("event") CustomCart cart) {
model.addAttribute("orderType", cart.getOrderType());
model.addAttribute("items", cart.getProucts()); Quantity amount = Quantity.of(number);
model.addAttribute("productForm", new ProductForm()); Quantity invAmount = inventory.findByProduct(product).get().getQuantity(); // TODO ERROR HANDLING
Quantity cartQuantity = cart.getQuantity(product);
// check for possible miss-inputs
if (amount.add(cartQuantity).isGreaterThan(invAmount)) {
cart.addOrUpdateItem(product, cartQuantity.negate().add(invAmount));
} else if (amount.add(cartQuantity).isLessThan(Quantity.of(0))) {
cart.addOrUpdateItem(product, cartQuantity.negate());
} else {
cart.addOrUpdateItem(product, amount);
}
return "redirect:/event"; return "redirect:/event";
} }
@PostMapping("/event/checkout") @PostMapping("/event/checkout")
public String checkout(Model model) { @PreAuthorize("hasRole('CUSTOMER')")
LocalDateTime min = LocalDateTime.of(2023, (int) (Math.random() * 11 + 1.0), (int) (Math.random() * 27 + 1.0), (int) (Math.random() * 23 + 1.0), 0, 0); public String checkout(@ModelAttribute("event") CustomCart cart, @LoggedIn Optional<UserAccount> userAccount, Model model) {
CustomOrder myOrder = new CustomOrder( return userAccount.map(account -> {
cart.getOrderType(), CustomOrder myOrder = new CustomOrder(account.getId(), cart);
min, cart.addItemsTo(myOrder);
min.plusDays((int) (Math.random() * 5)).plusHours((int) (Math.random() * 10)), orderManagement.payOrder(myOrder); // TODO: change this later
cart.getProucts(), orderManagement.completeOrder(myOrder);
false, cart.clear();
Math.round(Math.random() * 10000)
);
orderRepository.addOrder(myOrder); List<CustomOrder> myOrders = orderManagement.findBy(account).stream().collect(Collectors.toList());
model.addAttribute("orders", orderRepository.getOrders());
model.addAttribute("total", orderRepository.getOrders().size()); return "redirect:/myOrders";
cart.resetCart(); }).orElse("redirect:/event");
return "redirect:/orders";
} }
@PostMapping("/event/changeOrderType") @PostMapping("/event/changeOrderType")
public String changeOrderType(@RequestParam(name = "orderType") Optional<String> optionalOrderType, Model model) { @PreAuthorize("hasRole('CUSTOMER')")
public String changeOrderType(@RequestParam(name = "type") Optional<String> optionalOrderType, @ModelAttribute("event") CustomCart cart) {
String orderType = optionalOrderType.orElse("FOO"); String orderType = optionalOrderType.orElse("FOO");
switch (orderType) { switch (orderType) {
case "RaK": case "RaK":
cart.setOrderType(CustomOrder.OrderType.RENT_A_COOK); cart.setOrderType(OrderType.RENT_A_COOK);
break; break;
case "EK": case "EK":
cart.setOrderType(CustomOrder.OrderType.EVENT_CATERING); cart.setOrderType(OrderType.EVENT_CATERING);
break; break;
case "SN": case "SN":
cart.setOrderType(CustomOrder.OrderType.SUSHI_NIGHT); cart.setOrderType(OrderType.SUSHI_NIGHT);
break;
case "MB":
cart.setOrderType(OrderType.MOBILE_BREAKFAST);
break; break;
default: default:
cart.setOrderType(OrderType.SOMETHING_ELSE);
} }
return "redirect:/event"; return "redirect:/event";
} }
@GetMapping("/orders/calender") @PostMapping("/event/changeOrderTime")
public String calender(Model model) { @PreAuthorize("hasRole('CUSTOMER')")
LocalDate startDate = LocalDate.now(); public String changeOrderTime(@RequestParam(name = "start") Optional<String> startTime, @RequestParam(name = "finish") Optional<String> finishTime, @ModelAttribute("event") CustomCart cart) {
LocalDateTime start = LocalDateTime.parse(startTime.orElse("2024-12-03T10:15:30"));
LocalDateTime finish = LocalDateTime.parse(finishTime.orElse("2024-12-03T10:19:30"));
ArrayList<ArrayList<ArrayList<String>>> weeksOfMonth = new ArrayList<ArrayList<ArrayList<String>>>(4); cart.setStart(start);
for (int i = 0; i < 4; i++) { cart.setFinish(finish);
ArrayList<LocalDate> datesOfTheWeek = new ArrayList<LocalDate>(7);
LocalDate startOfWeek = startDate.plusDays(7*i);
LocalDate endOfWeekDate = startOfWeek.plusDays(6);
for (LocalDate date = startOfWeek; !date.isAfter(endOfWeekDate); date = date.plusDays(1)) {
datesOfTheWeek.add(date);
}
ArrayList<ArrayList<String>> week_to_add_to_month = new ArrayList<ArrayList<String>>(7); return "redirect:/event";
for (LocalDate date : datesOfTheWeek) {
ArrayList<String> x = new ArrayList<String>(2);
x.add(Integer.toString(date.getDayOfMonth()));
x.add(date.format(DateTimeFormatter.ISO_LOCAL_DATE));
week_to_add_to_month.add(x);
}
//datesOfTheWeek.clear();
weeksOfMonth.add(week_to_add_to_month);
}
LocalDate endDate = startDate.plusDays(27);
// get orders_in_next_month (in future sorted by endDate)
Iterable<CustomOrder> orders_in_next_month = this.orderRepository.getOrders().stream().filter(e ->
!e.getFinish().toLocalDate().isBefore(startDate) && // end is not before today
!e.getStart().toLocalDate().isAfter(endDate)).toList();
for (CustomOrder order : orders_in_next_month) {
int start_index_inclusive = Math.max((int) startDate.until(order.getStart().toLocalDate(), ChronoUnit.DAYS),0);
int end_index_exclusive = Math.min((int) startDate.until(order.getFinish().toLocalDate(), ChronoUnit.DAYS), 27) + 1;
for (int i = start_index_inclusive; i < end_index_exclusive; i++) {
weeksOfMonth.get(Math.floorDiv(i,7)).get(Math.floorMod(i,7)).add(Integer.toString(order.getId()));
}
}
// for (List<List<String>> orders_in_next_week : orders_in_next_month) {
// orders_in_next_weeks.stream().filter(e ->
// e.start.toLocalDate().isEqual(calender_day) || // start day
// e.end.toLocalDate().isEqual(calender_day) || // end day
// e.start.toLocalDate().isBefore(calender_day) && end.toLocalDate().isAfter(calender_day) // day in between start and end
// ).toList().count();
// }
// calendar header with names of week
LocalDate endOfWeekDate = startDate.plusDays(6);
ArrayList<String> dayNames = new ArrayList<String>(7);
for (LocalDate date = startDate; !date.isAfter(endOfWeekDate); date = date.plusDays(1)) {
dayNames.add(date.getDayOfWeek().toString());
}
model.addAttribute("weeksOfMonth", weeksOfMonth);
model.addAttribute("dayNames", dayNames);
return "orders_calender";
} }
} }

View file

@ -0,0 +1,9 @@
package catering.order;
public enum OrderType {
RENT_A_COOK,
EVENT_CATERING,
SUSHI_NIGHT,
MOBILE_BREAKFAST,
SOMETHING_ELSE
}

View file

@ -1,24 +0,0 @@
package catering.order;
import org.springframework.web.bind.annotation.ModelAttribute;
public class ProductForm {
private String product;
private int number;
public String getProduct() {
return product;
}
public int getNumber() {
return number;
}
public void setProduct(String product) {
this.product = product;
}
public void setNumber(int number) {
this.number = number;
}
}

View file

@ -6,15 +6,16 @@
<body> <body>
<div layout:fragment="content"> <div layout:fragment="content">
<span th:text="'Typ: ' + ${orderType}"/> <span th:text="'Typ: ' + ${event.getOrderType()}"/>
<form th:action="@{/event/changeOrderType}" method="post"> <form th:action="@{/event/changeOrderType}" method="post">
<select class="form-select w-auto d-inline-block" name="orderType"> <select class="form-select w-auto d-inline-block" name="type">
<option disabled="disabled" selected value="NULL" th:text="' -- Wählen Sie eine Option -- '"/> <option disabled="disabled" selected value="NULL" th:text="' -- Wählen Sie eine Option -- '"/>
<option th:value="'SE'" th:text="'Something else'"/> <option th:value="'SE'" th:text="'Something else'"/>
<option th:value="'RaK'" th:text="Rent-a-Cook"/> <option th:value="'RaK'" th:text="Rent-a-Cook"/>
<option th:value="'EK'" th:text="Eventcatering"/> <option th:value="'EK'" th:text="Eventcatering"/>
<option th:value="'SN'" th:text="'Sushi Night'"/> <option th:value="'SN'" th:text="'Sushi Night'"/>
<option th:value="'MB'" th:text="'Mobile Breakfase'"/>
</select> </select>
<button class="btn btn-primary" type="submit">Eventtypen ändern</button> <button class="btn btn-primary" type="submit">Eventtypen ändern</button>
</form> </form>
@ -23,33 +24,46 @@
<tr> <tr>
<th>Produkt</th> <th>Produkt</th>
<th>Anzahl</th> <th>Anzahl</th>
<th>Preis</th>
</tr> </tr>
<tr th:each="key : ${items.keySet()}"> <tr th:each="item : ${items}">
<td th:text="${key}">Sake Nigiri</td> <td th:text="${item.getProductName()}">Sake Nigiri</td>
<td th:text="${items.get(key)}">200</td> <td th:text="${item.getQuantity()}">200</td>
<td th:text="${item.getPrice()} +'€'">10€</td>
</tr> </tr>
</table> </table>
<h4>Product hinzufügen</h4> <span th:text="'Gesamt: ' + ${totalPrice}">Price</span>
<div class="mb-4">
<form th:action="@{/event/addProduct}" th:object="${productForm}" method="post">
<div class="mb-3">
<label class="form-label">Produkt</label>
<input class="form-control" type="text" th:field="*{product}" placeholder="Produktname" required/>
</div>
<div class="mb-3">
<label class="form-label">Anzahl</label>
<input class="form-control" type="number" th:field="*{number}" placeholder="Anzahl" min="1" required/>
</div>
<button class="btn btn-primary" type="submit">Submit</button>
</form>
</div>
<form method="post" th:action="@{/event/checkout}"> <form method="post" th:action="@{/event/checkout}">
<button class="btn btn-primary" type="submit">Kostenpflichtig bestellen</button> <button class="btn btn-primary" type="submit">Kostenpflichtig bestellen</button>
</form> </form>
<!-- I NEED SPACE -->
<br>
<br>
<h4>Produkt hinzufügen</h4>
<table class="table">
<tr>
<th>Name</th>
<th>Preis/Stück</th>
<th>Verfügbar</th>
<th>Menge</th>
</tr>
<tr th:each="item : ${invItems}">
<td th:text="${item.getProduct().getName()}">Name</td>
<td th:text="${item.getProduct().getPrice()}">Preis</td>
<td th:text="${item.getQuantity()}">Verfügbar</td>
<td>
<form th:action="@{/event/addProduct}" method="post">
<input id="number" type="number" name="number" th:min="${item.getQuantity().negate()}" th:max="${item.getQuantity()}" value="1"/>
<input type="hidden" name="pid" th:value="${item.getProduct().getId()}"/>
<input class="btn btn-primary" type="submit" th:value="Hinzufügen"/>
</form>
</td>
</tr>
</table>
</div> </div>
</html> </html>

View file

@ -25,12 +25,15 @@
<a class="nav-link" th:href="@{/customers}" sec:authorize="hasRole('ADMIN')">Kunden</a> <a class="nav-link" th:href="@{/customers}" sec:authorize="hasRole('ADMIN')">Kunden</a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" th:href="@{/orders}" sec:authorize="isAuthenticated()">Bestellungen</a> <a class="nav-link" th:href="@{/myOrders}" sec:authorize="hasRole('CUSTOMER')">Bestellungen</a>
</li>
<li class="nav-item">
<a class="nav-link" th:href="@{/allOrders}" sec:authorize="hasRole('ADMIN')">Bestellungen</a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" th:href="@{/event}" sec:authorize="hasRole('CUSTOMER')">Event planen</a> <a class="nav-link" th:href="@{/event}" sec:authorize="hasRole('CUSTOMER')">Event planen</a>
</li> </li>
<li class="nav-item"> <li class="nav-item"> <!--FIXME-->
<a class="nav-link" th:href="@{/orders/calender}" sec:authorize="hasRole('ADMIN')">Kalender</a> <a class="nav-link" th:href="@{/orders/calender}" sec:authorize="hasRole('ADMIN')">Kalender</a>
</li> </li>
</ul> </ul>

View file

@ -13,7 +13,7 @@
<th>Kunde</th> <th>Kunde</th>
<th>Produktdetails</th> <th>Produktdetails</th>
<th>Rechnung</th> <th>Rechnung</th>
<th>Bezahlt</th> <th>Status</th>
<th>Preis</th> <th>Preis</th>
<th></th> <th></th>
</tr> </tr>
@ -24,27 +24,27 @@
<td> <td>
<div> <div>
<a href="#productDetails" th:text="${order.getOrderType()}"/> <a href="#productDetails" th:text="${order.getOrderType()}"/>
<ul th:each="product : ${order.getFormattedProducts()}"> <ul th:each="chargeLine : ${order.getChargeLines()}">
<li th:text="${product}"/> <li th:text="${chargeLine}"/>
</ul> </ul>
</div> </div>
</td> </td>
<td> <td>
<div th:if="${order.invoiceAvailable()}"> <div th:if="${order.isInvoiceAvailable()}">
<a href="#invoice">Rechnung</a> <a href="#invoice">Rechnung</a>
</div> </div>
<div th:unless="${order.invoiceAvailable()}"> <div th:unless="${order.isInvoiceAvailable()}">
<span>Keine Rechnung verfügbar</span> <span>Keine Rechnung verfügbar</span>
</div> </div>
</td> </td>
<td>&#9746</td> <!--von Admin bearbeitbar--> <td th:text="${order.getOrderStatus()}"></td> <!--von Admin bearbeitbar-->
<td> <td>
<th:block th:text="${order.getTotalCost()}"/> <th:block th:text="${order.getTotal()}"/>
<th:block th:text="€"/> <th:block th:text="€"/>
</td> </td>
<td sec:authorize="hasRole('ADMIN')"> <td sec:authorize="hasRole('ADMIN')">
<form method="post" th:action="@{/orders/remove}"> <form method="post" th:action="@{/allOrders/remove}">
<input type="hidden" name="orderID" value="0" th:value="${order.getId()}"/> <input type="hidden" name="orderID" value="0" th:value="${order.getId()}"/> <!-- FIXME BROKEN -->
<input class="btn btn-danger" type="submit" value="remove" th:value="Entfernen"/> <input class="btn btn-danger" type="submit" value="remove" th:value="Entfernen"/>
</form> </form>
</td> </td>