diff --git a/src/main/java/catering/order/CustomCart.java b/src/main/java/catering/order/CustomCart.java index ccc29ed..1872538 100644 --- a/src/main/java/catering/order/CustomCart.java +++ b/src/main/java/catering/order/CustomCart.java @@ -1,45 +1,50 @@ package catering.order; -import org.salespointframework.quantity.Quantity; -import org.springframework.stereotype.Component; +import org.salespointframework.order.Cart; -import java.util.HashMap; -import java.util.Map; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +public class CustomCart extends Cart { + private OrderType orderType; + private LocalDateTime start; + private LocalDateTime finish; + private final String formatterPattern; -@Component -public class CustomCart { - private CustomOrder.OrderType orderType; - private Map products; - - public CustomCart() { - this.orderType = CustomOrder.OrderType.SOMETHING_ELSE; - this.products = new HashMap<>(); + // Constructor + public CustomCart(OrderType orderType, LocalDateTime start, LocalDateTime finish) { + super(); + this.orderType = orderType; + this.start = start; + this.finish = finish; + this.formatterPattern = "dd.MM.yyy, HH:mm 'Uhr'"; } - public CustomOrder.OrderType getOrderType() { + public OrderType getOrderType() { return orderType; } - public void setOrderType(CustomOrder.OrderType type) { - this.orderType = type; - return; + public void setOrderType(OrderType orderType) { + this.orderType = orderType; } - public Map getProucts() { - return products; + public LocalDateTime getStart() { + return start; } - public void addProduct(String product, int number) { - products.put(product, Quantity.of(number)); + public void setStart(LocalDateTime start) { + this.start = start; } - public boolean removeProduct(String product) { - return products.remove(product) != null; + public LocalDateTime getFinish() { + return finish; } - public void resetCart() { - orderType = CustomOrder.OrderType.SOMETHING_ELSE; - products = new HashMap<>(); + public void setFinish(LocalDateTime finish) { + this.finish = finish; + } + + public String getFormatterPattern() { + return formatterPattern; } } diff --git a/src/main/java/catering/order/CustomOrder.java b/src/main/java/catering/order/CustomOrder.java index f694f57..f7e0fc3 100644 --- a/src/main/java/catering/order/CustomOrder.java +++ b/src/main/java/catering/order/CustomOrder.java @@ -1,43 +1,32 @@ package catering.order; -import com.querydsl.core.Tuple; -import org.aspectj.weaver.ast.Or; -import org.salespointframework.quantity.Quantity; +import jakarta.persistence.Entity; +import org.salespointframework.order.Order; +import org.salespointframework.payment.Cash; +import org.salespointframework.useraccount.UserAccount; +import org.springframework.stereotype.Component; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Map; -/** - * This class is only used for the prototype to avoid using the bloated Salespoint API - */ -public class CustomOrder { - - private int id; - private OrderType orderType; +@Entity +public class CustomOrder extends Order { + private OrderType orderType = OrderType.SOMETHING_ELSE; private LocalDateTime start; private LocalDateTime finish; - private Map products; - private boolean invoiceAvailable; - private double totalCost; // this is in € - private DateTimeFormatter formatter; + private boolean invoiceAvailable = false; + private String formatterPattern = "dd.MM.yyy, HH:mm 'Uhr'"; - public CustomOrder(OrderType orderType, LocalDateTime start, LocalDateTime finish, Map products, boolean invoiceAvailable, double totalCost) { - this.id = (int) (Math.random() * Integer.MAX_VALUE); - this.orderType = orderType; - this.start = start; - this.finish = finish; - this.products = products; - this.invoiceAvailable = invoiceAvailable; - this.totalCost = totalCost; - this.formatter = DateTimeFormatter.ofPattern("dd.MM.yyy, HH:mm 'Uhr'"); + // Constructor + public CustomOrder(UserAccount.UserAccountIdentifier identifier, CustomCart cart) { + super(identifier, Cash.CASH); + this.orderType = cart.getOrderType(); + this.start = cart.getStart(); + this.finish = cart.getFinish(); + this.formatterPattern = cart.getFormatterPattern(); } - public int getId() { - return id; - } + public CustomOrder() {} // TODO: find out, why this is mandatory public OrderType getOrderType() { return orderType; @@ -48,7 +37,11 @@ public class CustomOrder { } public String getFormattedStart() { - return start.format(formatter); + return start.format(DateTimeFormatter.ofPattern(formatterPattern)); + } + + public void setStart(LocalDateTime start) { + this.start = start; } public LocalDateTime getFinish() { @@ -56,31 +49,18 @@ public class CustomOrder { } public String getFormattedFinish() { - return finish.format(formatter); + return finish.format(DateTimeFormatter.ofPattern(formatterPattern)); } - public Map getProducts() { - return products; + public void setFinish(LocalDateTime finish) { + this.finish = finish; } - public Collection getFormattedProducts() { - ArrayList formattedProducts = new ArrayList<>(); - getProducts().forEach((k, v) -> formattedProducts.add(k + ": " + v)); - return formattedProducts; - } - - public boolean invoiceAvailable() { + public boolean isInvoiceAvailable() { return invoiceAvailable; } - public double getTotalCost() { - return totalCost; - } - - enum OrderType { - RENT_A_COOK, - EVENT_CATERING, - SUSHI_NIGHT, - SOMETHING_ELSE + public void setInvoiceAvailable(boolean available) { + this.invoiceAvailable = available; } } diff --git a/src/main/java/catering/order/CustomOrderDataInitializer.java b/src/main/java/catering/order/CustomOrderDataInitializer.java deleted file mode 100644 index 29e33b2..0000000 --- a/src/main/java/catering/order/CustomOrderDataInitializer.java +++ /dev/null @@ -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 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 - )); - } -} diff --git a/src/main/java/catering/order/CustomOrderRepository.java b/src/main/java/catering/order/CustomOrderRepository.java deleted file mode 100644 index 8ef1831..0000000 --- a/src/main/java/catering/order/CustomOrderRepository.java +++ /dev/null @@ -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 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 getOrders() { - return new ArrayList<>(this.orders); - } - - // For Theo: returns all orders that happen on this day - public Collection 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()); - } -} diff --git a/src/main/java/catering/order/OrderController.java b/src/main/java/catering/order/OrderController.java index ca2cd18..2f0cef4 100644 --- a/src/main/java/catering/order/OrderController.java +++ b/src/main/java/catering/order/OrderController.java @@ -1,6 +1,18 @@ 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.ui.Model; import org.springframework.web.bind.annotation.*; @@ -11,159 +23,158 @@ import java.time.temporal.ChronoUnit; import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.Collection; -import java.util.Comparator; +import java.util.List; import java.util.Optional; +import java.util.stream.Collectors; @Controller +@PreAuthorize("isAuthenticated()") +@SessionAttributes("event") public class OrderController { - private final CustomOrderRepository orderRepository; - private final CustomCart cart; + private final OrderManagement orderManagement; + private final UniqueInventory inventory; - public OrderController(CustomOrderRepository orderRepository, CustomCart cart) { - this.orderRepository = orderRepository; - this.cart = cart; + public OrderController(OrderManagement orderManagement, UniqueInventory inventory) { + this.orderManagement = orderManagement; + this.inventory = inventory; } - @GetMapping("/orders") - public String orders(Model model) { - model.addAttribute("orders", orderRepository.getOrders()); - model.addAttribute("total", orderRepository.getOrders().size()); - return "orders"; - } + @GetMapping("/myOrders") + @PreAuthorize("hasRole('CUSTOMER')") + public String orders(Model model, @LoggedIn Optional userAccount) { + List myOrders = orderManagement.findBy(userAccount.get()).stream().collect(Collectors.toList()); // to be changed - // 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 myOrders = orderRepository.getOrdersByDate(date); model.addAttribute("orders", myOrders); model.addAttribute("total", myOrders.size()); return "orders"; } + @GetMapping("/allOrders") + @PreAuthorize("hasRole('ADMIN')") + public String orders(Model model) { + List 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 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") - public String event(Model model) { - model.addAttribute("orderType", cart.getOrderType()); - model.addAttribute("items", cart.getProucts()); - model.addAttribute("productForm", new ProductForm()); + @PreAuthorize("hasRole('CUSTOMER')") + public String event(Model model, @ModelAttribute("event") CustomCart cart) { + model.addAttribute("items", cart.stream().collect(Collectors.toList())); + model.addAttribute("totalPrice", cart.getPrice()); + model.addAttribute("invItems", inventory.findAll().stream().collect(Collectors.toList())); return "event"; } - @PostMapping("/orders/remove") - public String removeOrder(@RequestParam int orderID) { - orderRepository.removeOrder(orderID); - return "redirect:/orders"; + @PostMapping("/allOrders/remove") + public String removeOrder(@RequestParam Order.OrderIdentifier orderID, @LoggedIn Optional userAccount) { + return userAccount.map(account -> { + 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") - public String addProduct(@ModelAttribute ProductForm productForm, Model model) { - cart.addProduct(productForm.getProduct(), productForm.getNumber()); - model.addAttribute("orderType", cart.getOrderType()); - model.addAttribute("items", cart.getProucts()); - model.addAttribute("productForm", new ProductForm()); + @PreAuthorize("hasRole('CUSTOMER')") + public String addProduct(@RequestParam("pid") Product product, @RequestParam("number") int number, @ModelAttribute("event") CustomCart cart) { + + Quantity amount = Quantity.of(number); + 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"; } @PostMapping("/event/checkout") - public String checkout(Model model) { - 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); + @PreAuthorize("hasRole('CUSTOMER')") + public String checkout(@ModelAttribute("event") CustomCart cart, @LoggedIn Optional userAccount, Model model) { - CustomOrder myOrder = new CustomOrder( - cart.getOrderType(), - min, - min.plusDays((int) (Math.random() * 5)).plusHours((int) (Math.random() * 10)), - cart.getProucts(), - false, - Math.round(Math.random() * 10000) - ); + return userAccount.map(account -> { + CustomOrder myOrder = new CustomOrder(account.getId(), cart); + cart.addItemsTo(myOrder); + orderManagement.payOrder(myOrder); // TODO: change this later + orderManagement.completeOrder(myOrder); + cart.clear(); - orderRepository.addOrder(myOrder); - model.addAttribute("orders", orderRepository.getOrders()); - model.addAttribute("total", orderRepository.getOrders().size()); - cart.resetCart(); - return "redirect:/orders"; + List myOrders = orderManagement.findBy(account).stream().collect(Collectors.toList()); + + return "redirect:/myOrders"; + }).orElse("redirect:/event"); } @PostMapping("/event/changeOrderType") - public String changeOrderType(@RequestParam(name = "orderType") Optional optionalOrderType, Model model) { + @PreAuthorize("hasRole('CUSTOMER')") + public String changeOrderType(@RequestParam(name = "type") Optional optionalOrderType, @ModelAttribute("event") CustomCart cart) { String orderType = optionalOrderType.orElse("FOO"); switch (orderType) { case "RaK": - cart.setOrderType(CustomOrder.OrderType.RENT_A_COOK); + cart.setOrderType(OrderType.RENT_A_COOK); break; case "EK": - cart.setOrderType(CustomOrder.OrderType.EVENT_CATERING); + cart.setOrderType(OrderType.EVENT_CATERING); break; case "SN": - cart.setOrderType(CustomOrder.OrderType.SUSHI_NIGHT); + cart.setOrderType(OrderType.SUSHI_NIGHT); + break; + case "MB": + cart.setOrderType(OrderType.MOBILE_BREAKFAST); break; default: + cart.setOrderType(OrderType.SOMETHING_ELSE); } - return "redirect:/event"; } - @GetMapping("/orders/calender") - public String calender(Model model) { - LocalDate startDate = LocalDate.now(); + @PostMapping("/event/changeOrderTime") + @PreAuthorize("hasRole('CUSTOMER')") + public String changeOrderTime(@RequestParam(name = "start") Optional startTime, @RequestParam(name = "finish") Optional 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>> weeksOfMonth = new ArrayList>>(4); - for (int i = 0; i < 4; i++) { - ArrayList datesOfTheWeek = new ArrayList(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); - } + cart.setStart(start); + cart.setFinish(finish); - ArrayList> week_to_add_to_month = new ArrayList>(7); - for (LocalDate date : datesOfTheWeek) { - ArrayList x = new ArrayList(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 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> 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 dayNames = new ArrayList(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"; + return "redirect:/event"; } } diff --git a/src/main/java/catering/order/OrderType.java b/src/main/java/catering/order/OrderType.java new file mode 100644 index 0000000..7b8a682 --- /dev/null +++ b/src/main/java/catering/order/OrderType.java @@ -0,0 +1,9 @@ +package catering.order; + +public enum OrderType { + RENT_A_COOK, + EVENT_CATERING, + SUSHI_NIGHT, + MOBILE_BREAKFAST, + SOMETHING_ELSE +} diff --git a/src/main/java/catering/order/ProductForm.java b/src/main/java/catering/order/ProductForm.java deleted file mode 100644 index 4a22739..0000000 --- a/src/main/java/catering/order/ProductForm.java +++ /dev/null @@ -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; - } -} diff --git a/src/main/resources/templates/event.html b/src/main/resources/templates/event.html index e9c8c64..3eba2eb 100644 --- a/src/main/resources/templates/event.html +++ b/src/main/resources/templates/event.html @@ -6,15 +6,16 @@
- +
-
@@ -23,33 +24,46 @@ Produkt Anzahl + Preis - - Sake Nigiri - 200 + + Sake Nigiri + 200 + 10€ -

Product hinzufügen

- -
-
-
- - -
- -
- - -
- - -
-
+ Price
+ + +
+
+ +

Produkt hinzufügen

+ + + + + + + + + + + + + + +
NamePreis/StückVerfügbarMenge
NamePreisVerfügbar +
+ + + +
+
diff --git a/src/main/resources/templates/navigation.html b/src/main/resources/templates/navigation.html index 5e9370f..8397d0c 100644 --- a/src/main/resources/templates/navigation.html +++ b/src/main/resources/templates/navigation.html @@ -25,12 +25,15 @@ Kunden + - diff --git a/src/main/resources/templates/orders.html b/src/main/resources/templates/orders.html index 515f9e1..1116d70 100644 --- a/src/main/resources/templates/orders.html +++ b/src/main/resources/templates/orders.html @@ -13,7 +13,7 @@ Kunde Produktdetails Rechnung - Bezahlt + Status Preis @@ -24,27 +24,27 @@ -
+ -
+
Keine Rechnung verfügbar
- ☒ + - + -
- + +