Add additional functionality to order package

This adds improved product removal from cart, changeable order time and
nice colors to order list.

Works on #38
This commit is contained in:
Mathis Kral 2023-11-20 22:08:08 +01:00 committed by Simon Bruder
parent ea24c27d6e
commit 27fdc3ef02
Signed by: simon
GPG key ID: 8D3C82F9F309F8EC
3 changed files with 84 additions and 21 deletions

View file

@ -1,17 +1,17 @@
package catering.order; package catering.order;
import jakarta.persistence.PostPersist;
import org.salespointframework.catalog.Product; import org.salespointframework.catalog.Product;
import org.salespointframework.inventory.UniqueInventory; import org.salespointframework.inventory.UniqueInventory;
import org.salespointframework.inventory.UniqueInventoryItem; import org.salespointframework.inventory.UniqueInventoryItem;
import org.salespointframework.order.Cart; import org.salespointframework.order.*;
import org.salespointframework.order.Order;
import org.salespointframework.order.OrderManagement;
import org.salespointframework.quantity.Quantity; import org.salespointframework.quantity.Quantity;
import org.salespointframework.time.Interval; import org.salespointframework.time.Interval;
import org.salespointframework.useraccount.Role; import org.salespointframework.useraccount.Role;
import org.salespointframework.useraccount.UserAccount; import org.salespointframework.useraccount.UserAccount;
import org.salespointframework.useraccount.web.LoggedIn; import org.salespointframework.useraccount.web.LoggedIn;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.query.Procedure;
import org.springframework.security.access.prepost.PreAuthorize; 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;
@ -19,8 +19,10 @@ import org.springframework.web.bind.annotation.*;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.time.LocalDate; import java.time.LocalDate;
import java.time.LocalTime;
import java.time.temporal.ChronoUnit; import java.time.temporal.ChronoUnit;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalUnit;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
@ -48,6 +50,8 @@ public class OrderController {
model.addAttribute("orders", myOrders); model.addAttribute("orders", myOrders);
model.addAttribute("total", myOrders.size()); model.addAttribute("total", myOrders.size());
model.addAttribute("cancelled", OrderStatus.CANCELED);
model.addAttribute("completed", OrderStatus.COMPLETED);
return "orders"; return "orders";
} }
@ -58,6 +62,8 @@ public class OrderController {
model.addAttribute("orders", myOrders); model.addAttribute("orders", myOrders);
model.addAttribute("total", myOrders.size()); model.addAttribute("total", myOrders.size());
model.addAttribute("cancelled", OrderStatus.CANCELED);
model.addAttribute("completed", OrderStatus.COMPLETED);
return "orders"; return "orders";
} }
@ -81,7 +87,7 @@ public class OrderController {
@ModelAttribute("event") @ModelAttribute("event")
CustomCart initializeCart() { CustomCart initializeCart() {
return new CustomCart(OrderType.SOMETHING_ELSE, LocalDateTime.now(), LocalDateTime.now()); return new CustomCart(OrderType.SOMETHING_ELSE, LocalDateTime.now().plusDays(7), LocalDateTime.now().plusDays(7));
} }
@GetMapping("/event") @GetMapping("/event")
@ -110,15 +116,13 @@ public class OrderController {
@PreAuthorize("hasRole('CUSTOMER')") @PreAuthorize("hasRole('CUSTOMER')")
public String addProduct(@RequestParam("pid") Product product, @RequestParam("number") int number, @ModelAttribute("event") CustomCart cart) { public String addProduct(@RequestParam("pid") Product product, @RequestParam("number") int number, @ModelAttribute("event") CustomCart cart) {
Quantity amount = Quantity.of(number); Quantity amount = Quantity.of(number > 0 ? number : 1);
Quantity invAmount = inventory.findByProduct(product).get().getQuantity(); // TODO ERROR HANDLING Quantity invAmount = inventory.findByProduct(product).get().getQuantity(); // TODO ERROR HANDLING
Quantity cartQuantity = cart.getQuantity(product); Quantity cartQuantity = cart.getQuantity(product);
// check for possible miss-inputs // check for possible miss-inputs
if (amount.add(cartQuantity).isGreaterThan(invAmount)) { if (amount.add(cartQuantity).isGreaterThan(invAmount)) {
cart.addOrUpdateItem(product, cartQuantity.negate().add(invAmount)); cart.addOrUpdateItem(product, cartQuantity.negate().add(invAmount));
} else if (amount.add(cartQuantity).isLessThan(Quantity.of(0))) {
cart.addOrUpdateItem(product, cartQuantity.negate());
} else { } else {
cart.addOrUpdateItem(product, amount); cart.addOrUpdateItem(product, amount);
} }
@ -126,9 +130,37 @@ public class OrderController {
return "redirect:/event"; return "redirect:/event";
} }
@PostMapping("/event/removeProduct")
@PreAuthorize("hasRole('CUSTOMER')")
public String removeProduct(@RequestParam("itemId") String itemId, @ModelAttribute("event") CustomCart cart) {
cart.removeItem(itemId);
return "redirect:/event";
}
@PostMapping("/event/changeDate")
@PreAuthorize("hasRole('CUSTOMER')")
public String changeDate(@RequestParam("startDate") LocalDate start, @RequestParam("startHour") Optional<Integer> startHour, @RequestParam("finishDate") LocalDate finish, @RequestParam("finishHour") Optional<Integer> finishHour, @ModelAttribute("event") CustomCart cart) {
int unwrappedStartHour = startHour.orElse(cart.getStart().getHour());
int unwrappedFinishHour = finishHour.orElse(cart.getFinish().getHour());
finish = finish.isBefore(start) ? start : finish;
LocalDateTime startTime = LocalDateTime.of(start, LocalTime.of(unwrappedStartHour, 0)); // TODO
LocalDateTime finishTime = LocalDateTime.of(finish, LocalTime.of(unwrappedFinishHour <= unwrappedStartHour ? unwrappedStartHour+1 : unwrappedFinishHour, 0)); // TODO
cart.setStart(startTime);
cart.setFinish(finishTime);
return "redirect:/event";
}
@PostMapping("/event/checkout") @PostMapping("/event/checkout")
@PreAuthorize("hasRole('CUSTOMER')") @PreAuthorize("hasRole('CUSTOMER')")
public String checkout(@ModelAttribute("event") CustomCart cart, @LoggedIn Optional<UserAccount> userAccount, Model model) { public String checkout(@ModelAttribute("event") CustomCart cart, @LoggedIn Optional<UserAccount> userAccount) {
if (cart.isEmpty()) {
return "redirect:/event";
}
return userAccount.map(account -> { return userAccount.map(account -> {
CustomOrder myOrder = new CustomOrder(account.getId(), cart); CustomOrder myOrder = new CustomOrder(account.getId(), cart);
@ -137,8 +169,6 @@ public class OrderController {
orderManagement.completeOrder(myOrder); orderManagement.completeOrder(myOrder);
cart.clear(); cart.clear();
List<CustomOrder> myOrders = orderManagement.findBy(account).stream().collect(Collectors.toList());
return "redirect:/myOrders"; return "redirect:/myOrders";
}).orElse("redirect:/event"); }).orElse("redirect:/event");
} }

View file

@ -6,11 +6,9 @@
<body> <body>
<div layout:fragment="content"> <div layout:fragment="content">
<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="type"> <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="${event.getOrderType()}"/>
<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"/>
@ -20,16 +18,44 @@
<button class="btn btn-primary" type="submit">Eventtypen ändern</button> <button class="btn btn-primary" type="submit">Eventtypen ändern</button>
</form> </form>
<!-- I NEED SPACE -->
<br>
<form th:action="@{/event/changeDate}" method="post">
<label th:text="'Wählen sie ihren gewünschten Zeitraum aus (min. 7 Tage im voraus):'"/><br>
<input type="date" th:value="${event.getStart().toLocalDate()}" th:min="${event.getStart().toLocalDate()}" name="startDate"/>
<select class="i do not know" name="startHour">
<option disabled="disabled" selected value="NULL" th:text="${event.getStart().getHour()} + ' Uhr'"/>
<option th:each="i : ${#numbers.sequence(0, 23)}" th:value="${i}" th:text="${i} + ' Uhr'"></option>
</select>
<input type="date" th:value="${event.getFinish().toLocalDate()}" th:min="${event.getFinish().toLocalDate()}" name="finishDate"/>
<select class="i do not know" name="finishHour">
<option disabled="disabled" selected value="NULL" th:text="${event.getFinish().getHour() + ' Uhr'}"/>
<option th:each="i : ${#numbers.sequence(0, 23)}" th:value="${i}" th:text="${i} + ' Uhr'"></option>
</select>
<button class="btn btn-primary" type="submit">Wunschdatum überprüfen</button>
</form>
<!-- I NEED SPACE -->
<br>
<table class="table"> <table class="table">
<tr> <tr>
<th>Produkt</th> <th>Produkt</th>
<th>Anzahl</th> <th>Anzahl</th>
<th>Preis</th> <th>Preis</th>
<th></th>
</tr> </tr>
<tr th:each="item : ${items}"> <tr th:each="item : ${items}">
<td th:text="${item.getProductName()}">Sake Nigiri</td> <td th:text="${item.getProductName()}">Sake Nigiri</td>
<td th:text="${item.getQuantity()}">200</td> <td th:text="${item.getQuantity()}">200</td>
<td th:text="${item.getPrice()} +'€'">10€</td> <td th:text="${item.getPrice()} +'€'">10€</td>
<td>
<form method="post" th:action="@{/event/removeProduct}">
<input type="hidden" th:value="${item.getId()}" name="itemId"/>
<button class="btn btn-danger" type="submit" >Produkt entfernen</button>
</form>
</td>
</tr> </tr>
</table> </table>
@ -58,7 +84,7 @@
<td th:text="${item.getQuantity()}">Verfügbar</td> <td th:text="${item.getQuantity()}">Verfügbar</td>
<td> <td>
<form th:action="@{/event/addProduct}" method="post"> <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 id="number" type="number" name="number" min="1" th:max="${item.getQuantity()}" value="1"/>
<input type="hidden" name="pid" th:value="${item.getProduct().getId()}"/> <input type="hidden" name="pid" th:value="${item.getProduct().getId()}"/>
<input class="btn btn-primary" type="submit" th:value="Hinzufügen"/> <input class="btn btn-primary" type="submit" th:value="Hinzufügen"/>
</form> </form>

View file

@ -20,12 +20,16 @@
<tr th:each="order : ${orders}"> <tr th:each="order : ${orders}">
<td th:text="${order.getFormattedStart()}"> <td th:text="${order.getFormattedStart()}">
<td th:text="${order.getFormattedFinish()}"> <td th:text="${order.getFormattedFinish()}">
<td th:text="BeispielKunde"/> <td th:text="${order.getUserAccountIdentifier()}"/>
<td> <td>
<div> <div>
<a href="#productDetails" th:text="${order.getOrderType()}"/> <a href="#productDetails" th:text="${order.getOrderType()}"/>
<ul th:each="chargeLine : ${order.getChargeLines()}"> <ul th:each="orderLine : ${order.getOrderLines()}">
<li th:text="${chargeLine}"/> <li>
<b th:text="${orderLine.getProductName()}"/><br>
<th:block th:text="'Menge: ' + ${orderLine.getQuantity()}"/><br>
<th:block th:text="'Preis: ' + ${orderLine.getPrice().getNumber().doubleValue() + ' €'}"/>
</li>
</ul> </ul>
</div> </div>
</td> </td>
@ -37,15 +41,18 @@
<span>Keine Rechnung verfügbar</span> <span>Keine Rechnung verfügbar</span>
</div> </div>
</td> </td>
<td th:text="${order.getOrderStatus()}"></td> <!--von Admin bearbeitbar-->
<td> <td>
<th:block th:text="${order.getTotal()}"/> <p style="color: red" th:if="${order.getOrderStatus()} == ${cancelled}" th:text="STORNIERT"/>
<p style="color: green" th:if="${order.getOrderStatus()} == ${completed}" th:text="ABGESCHLOSSEN"/>
</td> <!--von Admin bearbeitbar-->
<td>
<th:block th:text="${order.getTotal().getNumber().doubleValue()}"/>
<th:block th:text="€"/> <th:block th:text="€"/>
</td> </td>
<td sec:authorize="hasRole('ADMIN')"> <td sec:authorize="hasRole('ADMIN')" th:if="${order.getOrderStatus()} != ${cancelled}">
<form method="post" th:action="@{/allOrders/remove}"> <form method="post" th:action="@{/allOrders/remove}">
<input type="hidden" name="orderID" value="0" th:value="${order.getId()}"/> <!-- FIXME BROKEN --> <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="Stornieren"/>
</form> </form>
</td> </td>
</tr> </tr>