mirror of
https://github.com/st-tu-dresden-praktikum/swt23w23
synced 2024-07-19 21:04:36 +02:00
Filter and distinguish products in orderCatalog
This commit is contained in:
parent
c94a4d4adb
commit
5aefd4e05f
|
@ -22,7 +22,7 @@ Files: src/main/asciidoc/models/analysis/*.svg
|
|||
src/main/asciidoc/models/design/*.svg
|
||||
src/main/asciidoc/models/mockups/*.svg
|
||||
src/main/resources/banner.txt
|
||||
Copyright: 2023 swt23w23
|
||||
Copyright: 2023-2024 swt23w23
|
||||
License: AGPL-3.0-or-later
|
||||
|
||||
# Small and/or autogenenerated files that can’t be copyrighted
|
||||
|
|
|
@ -267,6 +267,7 @@ image:models/design/orderCatalog.svg[class design diagram - OrderCatalog]
|
|||
|OrderCatalogController |A Spring MVC Controller to handle the event catalog
|
||||
|OrderCatalogEntry |A class to save an event pack created by the administrator
|
||||
|OrderCatalogEntryRepository |A repository to save all event packs in the form of OrderCatalogEntry
|
||||
|CartService |A service class to make sure that Order and OrderCatalog use the same CustomCart object
|
||||
|===
|
||||
|
||||
=== Order
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
' SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
' SPDX-FileCopyrightText: 2023 swt23w23
|
||||
' SPDX-FileCopyrightText: 2023-2024 swt23w23
|
||||
@startuml
|
||||
skinparam linetype ortho
|
||||
skinparam groupInheritance 2
|
||||
|
@ -13,6 +13,7 @@ package Salespoint {
|
|||
class Quantity
|
||||
class UserAccount
|
||||
class Product
|
||||
class Inventory
|
||||
}
|
||||
|
||||
package catering.order {
|
||||
|
@ -23,34 +24,44 @@ package catering.orderCatalog {
|
|||
class OrderCatalogController {
|
||||
+ OrderCatalogController()
|
||||
+ catalog(model : Model) : String
|
||||
+ configureCatalog(model : Model) : String
|
||||
+ catalogAdd(eventType : OrderCatalogEntry.EventType, minimumTimePeriod : int, totalCost : int, model : Model) : String
|
||||
+ editCatalog(model : Model) : String
|
||||
+ addCatalogEntry(eventType : OrderCatalogEntry.EventType, minimumTimePeriod : int, totalCost : int, model : Model) : String
|
||||
+ removeEntry(catalogEntryID : int) : String
|
||||
+ addProduct(name : String, amount : int, cost : double) : String
|
||||
+ removeProduct(id : String, model : Model) : String
|
||||
+ addTime(minimumTimePeriod : int, eventType : OrderCatalogEntry.EventType, products : Collection<Salespoint.Product>, model : Model) : String
|
||||
+ chooseEvent(events : String) : String
|
||||
+ addToCart(catalogEntryID : long) : String
|
||||
}
|
||||
|
||||
class OrderCatalogEntry {
|
||||
- id : Long
|
||||
- eventType : OrderType
|
||||
- products : Map<Salespoint.Product, Salespoint.Quantity>
|
||||
- totalCost: double
|
||||
+ OrderCatalogEntry()
|
||||
+ getId() : int
|
||||
+ getEventType() : EventType
|
||||
+ getProducts() : Collection<Salespoint.Product>
|
||||
+ getMinimumTimePeriod() : int
|
||||
+ getTotalCost() : int
|
||||
+ setEventType(eventType : EventType) : void
|
||||
+ setMinimumTimePeriod(timePeriod : int) : void
|
||||
+ setTotalCost(totalCost : int) : void
|
||||
+ addProduct(name : String, count : Integer) : void
|
||||
+ getId() : long
|
||||
+ getEventType() : OrderType
|
||||
+ getProducts() : Map<Salespoint.Product, Salespoint.Quantity>
|
||||
+ getTotalCost() : double
|
||||
+ setEventType(eventType : OrderType) : void
|
||||
+ setTotalCost(totalCost : double) : void
|
||||
+ addProduct(product : Salespoint.Product, count : Salespoint.Quantity) : void
|
||||
+ setProducts(Map<Salespoint.Product, Salespoint.Quantity>) : void
|
||||
}
|
||||
|
||||
class OrderCatalogEntryRepository {
|
||||
interface OrderCatalogEntryRepository {
|
||||
+ OrderCatalogEntryRepository()
|
||||
+ addCatalogEntry(catalogEntry : OrderCatalogEntry) : boolean
|
||||
+ removeCatalogEntry(catalogEntryID : int) : boolean
|
||||
+ getCatalogEntries() : Set<OrderCatalogEntries>
|
||||
}
|
||||
|
||||
class CartService {
|
||||
- CustomCart cart
|
||||
+ CartService()
|
||||
+ getCart() : CustomCart
|
||||
+ setCart(CustomCart cart) : void
|
||||
}
|
||||
}
|
||||
|
||||
OrderCatalogEntryRepository o---> OrderCatalogEntry
|
||||
|
@ -62,5 +73,7 @@ OrderCatalogController ...> Salespoint.Cash
|
|||
OrderCatalogController ...> Salespoint.Quantity
|
||||
OrderCatalogController ...> Salespoint.UserAccount
|
||||
OrderCatalogEntry ...> catering.order.EventType
|
||||
CartService ...> catering.order.OrderController
|
||||
OrderCatalogController ...> Salespoint.Inventory
|
||||
|
||||
@enduml
|
||||
|
|
BIN
src/main/asciidoc/models/design/orderCatalog.svg
(Stored with Git LFS)
BIN
src/main/asciidoc/models/design/orderCatalog.svg
(Stored with Git LFS)
Binary file not shown.
|
@ -2,6 +2,7 @@
|
|||
// SPDX-FileCopyrightText: 2023-2024 swt23w23
|
||||
package catering.inventory;
|
||||
|
||||
import catering.orderCatalog.CustomCatalogEntryRepository;
|
||||
import org.salespointframework.catalog.Product;
|
||||
import org.salespointframework.inventory.UniqueInventory;
|
||||
import org.salespointframework.inventory.UniqueInventoryItem;
|
||||
|
@ -50,12 +51,14 @@ import jakarta.validation.Valid;
|
|||
class InventoryController {
|
||||
private final UniqueInventory<UniqueInventoryItem> inventory;
|
||||
private final CateringCatalog cateringCatalog;
|
||||
private final CustomCatalogEntryRepository catalogEntryRepository;
|
||||
|
||||
InventoryController(UniqueInventory<UniqueInventoryItem> inventory, CateringCatalog cateringCatalog) {
|
||||
InventoryController(UniqueInventory<UniqueInventoryItem> inventory, CateringCatalog cateringCatalog, CustomCatalogEntryRepository catalogEntryRepository) {
|
||||
Assert.notNull(inventory, "Inventory must not be null!");
|
||||
Assert.notNull(inventory, "CateringCatalog must not be null!");
|
||||
this.inventory = inventory;
|
||||
this.cateringCatalog = cateringCatalog;
|
||||
this.catalogEntryRepository = catalogEntryRepository;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -261,6 +264,7 @@ class InventoryController {
|
|||
@GetMapping("/inventory/delete/{pid}")
|
||||
String delete(@PathVariable Product pid) {
|
||||
UniqueInventoryItem item = inventory.findByProduct(pid).get();
|
||||
catalogEntryRepository.deleteAll(catalogEntryRepository.findByProduct(pid));
|
||||
inventory.delete(item);
|
||||
cateringCatalog.delete(pid);
|
||||
return "redirect:/inventory";
|
||||
|
|
|
@ -5,6 +5,7 @@ package catering.order;
|
|||
import catering.catalog.CateringCatalog;
|
||||
import catering.catalog.Consumable;
|
||||
import catering.catalog.Rentable;
|
||||
import catering.orderCatalog.CartService;
|
||||
import catering.staff.Employee;
|
||||
import catering.staff.JobType;
|
||||
import catering.staff.StaffManagement;
|
||||
|
@ -17,6 +18,7 @@ import org.salespointframework.quantity.Quantity;
|
|||
import org.salespointframework.useraccount.Role;
|
||||
import org.salespointframework.useraccount.UserAccount;
|
||||
import org.salespointframework.useraccount.web.LoggedIn;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.stereotype.Controller;
|
||||
|
@ -44,16 +46,21 @@ public class OrderController {
|
|||
private final CateringCatalog catalog;
|
||||
private final StaffManagement staffManagement;
|
||||
|
||||
@Autowired
|
||||
private CartService cartService;
|
||||
|
||||
public OrderController(OrderManagement<CustomOrder> orderManagement,
|
||||
CustomOrderRepository customOrderRepository,
|
||||
UniqueInventory<UniqueInventoryItem> inventory,
|
||||
CateringCatalog catalog,
|
||||
StaffManagement staffManagement) {
|
||||
StaffManagement staffManagement,
|
||||
CartService cartService) {
|
||||
this.orderManagement = orderManagement;
|
||||
this.customOrderRepository = customOrderRepository;
|
||||
this.catalog = catalog;
|
||||
this.inventory = inventory;
|
||||
this.staffManagement = staffManagement;
|
||||
this.cartService = cartService;
|
||||
}
|
||||
|
||||
@GetMapping("/myOrders")
|
||||
|
@ -109,8 +116,7 @@ public class OrderController {
|
|||
|
||||
@ModelAttribute("event")
|
||||
CustomCart initializeCart() {
|
||||
return new CustomCart(OrderType.EVENT_CATERING, LocalDateTime.now().plusDays(7),
|
||||
LocalDateTime.now().plusDays(7).plusHours(1));
|
||||
return cartService.getCart();
|
||||
}
|
||||
|
||||
@GetMapping("/event")
|
||||
|
|
29
src/main/java/catering/orderCatalog/CartService.java
Normal file
29
src/main/java/catering/orderCatalog/CartService.java
Normal file
|
@ -0,0 +1,29 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
// SPDX-FileCopyrightText: 2023-2024 swt23w23
|
||||
package catering.orderCatalog;
|
||||
|
||||
import catering.order.CustomCart;
|
||||
import catering.order.OrderType;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.context.annotation.ScopedProxyMode;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Service
|
||||
@Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
|
||||
public class CartService {
|
||||
private CustomCart cart;
|
||||
|
||||
public CartService() {
|
||||
this.cart = new CustomCart(OrderType.EVENT_CATERING, LocalDateTime.now().plusDays(7),
|
||||
LocalDateTime.now().plusDays(7).plusHours(1));
|
||||
}
|
||||
|
||||
public CustomCart getCart() {
|
||||
return cart;
|
||||
}
|
||||
public void setCart(CustomCart cart) {
|
||||
this.cart = cart;
|
||||
}
|
||||
}
|
|
@ -3,10 +3,14 @@
|
|||
package catering.orderCatalog;
|
||||
|
||||
import catering.order.OrderType;
|
||||
import catering.staff.Employee;
|
||||
import catering.staff.StaffManagement;
|
||||
import org.javamoney.moneta.Money;
|
||||
import org.salespointframework.catalog.Product;
|
||||
import org.salespointframework.inventory.UniqueInventory;
|
||||
import org.salespointframework.inventory.UniqueInventoryItem;
|
||||
import org.salespointframework.quantity.Quantity;
|
||||
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;
|
||||
|
@ -23,16 +27,20 @@ public class CatalogController {
|
|||
private CustomCatalogEntry formCatalogEntry;
|
||||
private final UniqueInventory<UniqueInventoryItem> inventory;
|
||||
|
||||
@Autowired
|
||||
private CartService cartService;
|
||||
|
||||
public CatalogController(CustomCatalogEntryRepository catalogEntryRepository,
|
||||
UniqueInventory<UniqueInventoryItem> inventory) {
|
||||
UniqueInventory<UniqueInventoryItem> inventory,
|
||||
CartService cartService) {
|
||||
productMap = new HashMap<>();
|
||||
formCatalogEntry = new CustomCatalogEntry(
|
||||
OrderType.EVENT_CATERING,
|
||||
new HashMap<String, Quantity>(),
|
||||
0,
|
||||
0);
|
||||
new HashMap<Product, Quantity>(),
|
||||
Money.of(0, "EUR"));
|
||||
this.catalogEntryRepository = catalogEntryRepository;
|
||||
this.inventory = inventory;
|
||||
this.cartService = cartService;
|
||||
}
|
||||
|
||||
@GetMapping("/catalog")
|
||||
|
@ -42,34 +50,35 @@ public class CatalogController {
|
|||
}
|
||||
|
||||
@GetMapping("/catalog_editor")
|
||||
public String editCatalog(Model model) {;
|
||||
public String editCatalog(Model model) {
|
||||
model.addAttribute("productMap", productMap);
|
||||
model.addAttribute("formCatalogEntry", formCatalogEntry);
|
||||
model.addAttribute("inventory", inventory.findAll().stream().collect(Collectors.toList()));
|
||||
model.addAttribute("inventory", inventory.findAll().stream()
|
||||
.filter(i -> i.getProduct()
|
||||
.getCategories()
|
||||
.stream().anyMatch(c -> c.equals(formCatalogEntry.getEventType().toString())))
|
||||
.collect(Collectors.toList()));
|
||||
return "catalog_editor";
|
||||
}
|
||||
|
||||
@PostMapping("/catalog_editor/addCatalogEntry")
|
||||
public String addCatalogEntry(@RequestParam OrderType eventType,
|
||||
@RequestParam int minimumTimePeriod,
|
||||
@RequestParam int totalCost,
|
||||
@RequestParam double totalCost,
|
||||
Model model) {
|
||||
Map<String, Quantity> products = new HashMap<String, Quantity>();
|
||||
Map<Product, Quantity> products = new HashMap<Product, Quantity>();
|
||||
|
||||
for (Product product : productMap.keySet()) {
|
||||
products.put(product.getName(), productMap.get(product));
|
||||
products.put(product, productMap.get(product));
|
||||
}
|
||||
|
||||
catalogEntryRepository.save(new CustomCatalogEntry(
|
||||
eventType,
|
||||
products,
|
||||
minimumTimePeriod,
|
||||
totalCost));
|
||||
Money.of(totalCost, "EUR")));
|
||||
this.formCatalogEntry = new CustomCatalogEntry(
|
||||
OrderType.EVENT_CATERING,
|
||||
new HashMap<String, Quantity>(),
|
||||
0,
|
||||
0);
|
||||
new HashMap<Product, Quantity>(),
|
||||
Money.of(0, "EUR"));
|
||||
productMap.clear();
|
||||
model.addAttribute("productMap", productMap);
|
||||
model.addAttribute("formCatalogEntry", formCatalogEntry);
|
||||
|
@ -86,10 +95,10 @@ public class CatalogController {
|
|||
|
||||
@PostMapping("/catalog_editor/addProduct")
|
||||
public String addProduct(@RequestParam("pid") Product product, @RequestParam("number") int number) {
|
||||
Quantity amount = Quantity.of(number);
|
||||
productMap.compute(product, (key, existingQuantity) ->
|
||||
(existingQuantity == null) ? amount : existingQuantity.add(amount));
|
||||
formCatalogEntry.addProduct(product.getName(), amount);
|
||||
Quantity amount = product.createQuantity(number);
|
||||
productMap.compute(product,
|
||||
(key, existingQuantity) -> (existingQuantity == null) ? amount : existingQuantity.add(amount));
|
||||
formCatalogEntry.addProduct(product, amount);
|
||||
return "redirect:/catalog_editor";
|
||||
}
|
||||
|
||||
|
@ -107,31 +116,41 @@ public class CatalogController {
|
|||
return "redirect:/catalog_editor";
|
||||
}
|
||||
|
||||
@PostMapping("/catalog_editor/addTime")
|
||||
public String addTime(@RequestParam int minimumTimePeriod,
|
||||
@RequestParam OrderType eventType,
|
||||
@RequestParam Map<String, Integer> products,
|
||||
Model model) {
|
||||
formCatalogEntry.setMinimumTimePeriod(minimumTimePeriod);
|
||||
model.addAttribute("formCatalogEntry", formCatalogEntry);
|
||||
return "redirect:/catalog_editor";
|
||||
}
|
||||
|
||||
@PostMapping("/catalog_editor/chooseEvent")
|
||||
public String chooseEvent(String events) {
|
||||
switch (events) {
|
||||
case "mobile_breakfast":
|
||||
formCatalogEntry.setEventType(OrderType.MOBILE_BREAKFAST);
|
||||
break;
|
||||
case "rent_a_cook":
|
||||
formCatalogEntry.setEventType(OrderType.RENT_A_COOK);
|
||||
break;
|
||||
default:
|
||||
public String chooseEvent(String eventType) {
|
||||
try {
|
||||
formCatalogEntry.setEventType(OrderType.valueOf(eventType));
|
||||
} catch (IllegalArgumentException e) {
|
||||
formCatalogEntry.setEventType(OrderType.EVENT_CATERING);
|
||||
break;
|
||||
}
|
||||
|
||||
productMap.clear();
|
||||
return "redirect:/catalog_editor";
|
||||
}
|
||||
|
||||
@PostMapping("/catalog/addToCart")
|
||||
public String addToCart(@RequestParam long catalogEntryID) {
|
||||
if (cartService.getCart() == null) {
|
||||
return "redirect:/event";
|
||||
}
|
||||
CustomCatalogEntry entry = catalogEntryRepository.findById(catalogEntryID).get();
|
||||
|
||||
for (Product product : entry.getProducts().keySet()) {
|
||||
// Checks if inventory has sufficient Quantity of a Product
|
||||
Quantity cartQuantity = cartService.getCart().getQuantity(product);
|
||||
|
||||
if (entry.getProducts().get(product).add(cartQuantity).isGreaterThan(
|
||||
inventory.findByProduct(product).get().getQuantity())) {
|
||||
cartService.getCart().addOrUpdateItem(
|
||||
product,
|
||||
inventory.findByProduct(product).get().getQuantity().subtract(cartQuantity));
|
||||
} else {
|
||||
cartService.getCart().addOrUpdateItem(
|
||||
product,
|
||||
entry.getProducts().get(product));
|
||||
}
|
||||
}
|
||||
cartService.getCart().setOrderType(entry.getEventType());
|
||||
|
||||
return "redirect:/event";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,9 +4,11 @@ package catering.orderCatalog;
|
|||
|
||||
import catering.order.OrderType;
|
||||
import jakarta.persistence.*;
|
||||
import org.javamoney.moneta.Money;
|
||||
import org.salespointframework.catalog.Product;
|
||||
import org.salespointframework.quantity.Quantity;
|
||||
|
||||
import java.util.Iterator;
|
||||
import javax.money.MonetaryAmount;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
|
@ -19,14 +21,12 @@ public class CustomCatalogEntry {
|
|||
private OrderType eventType;
|
||||
|
||||
@ElementCollection
|
||||
private Map<String, Quantity> products;
|
||||
private int minimumTimePeriod; // Declared as int for simplification of the prototype. Only whole hours.
|
||||
private int totalCost; // Should actually accumulate the price of all items.
|
||||
private Map<Product, Quantity> products;
|
||||
private MonetaryAmount totalCost;
|
||||
|
||||
public CustomCatalogEntry(OrderType eventType, Map<String, Quantity> products, int minimumTimePeriod, int totalCost) {
|
||||
public CustomCatalogEntry(OrderType eventType, Map<Product, Quantity> products, MonetaryAmount totalCost) {
|
||||
this.eventType = eventType;
|
||||
this.products = products;
|
||||
this.minimumTimePeriod = minimumTimePeriod;
|
||||
this.totalCost = totalCost;
|
||||
}
|
||||
|
||||
|
@ -42,21 +42,16 @@ public class CustomCatalogEntry {
|
|||
return eventType;
|
||||
}
|
||||
|
||||
public Map<String, Quantity> getProducts() {
|
||||
public Map<Product, Quantity> getProducts() {
|
||||
return products;
|
||||
}
|
||||
|
||||
public int getMinimumTimePeriod() {
|
||||
return minimumTimePeriod;
|
||||
}
|
||||
public MonetaryAmount getTotalCost() {
|
||||
MonetaryAmount totalCost = products.entrySet().stream()
|
||||
.map(e -> e.getKey().getPrice().multiply(e.getValue().getAmount().doubleValue()))
|
||||
.reduce(Money.of(0, "EUR"), MonetaryAmount::add);
|
||||
|
||||
public int getTotalCost() {
|
||||
totalCost = 0;
|
||||
Iterator<Quantity> iterator = products.values().iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Quantity currentQuantity = iterator.next();
|
||||
totalCost += currentQuantity.getAmount().intValue();
|
||||
}
|
||||
setTotalCost(totalCost);
|
||||
return totalCost;
|
||||
}
|
||||
|
||||
|
@ -64,18 +59,19 @@ public class CustomCatalogEntry {
|
|||
this.eventType = eventType;
|
||||
}
|
||||
|
||||
public void addProduct(String name, Quantity count) {
|
||||
this.products.put(name, count);
|
||||
public void addProduct(Product product, Quantity count) {
|
||||
if (products.containsKey(product)) {
|
||||
this.products.put(product, products.get(product).add(count));
|
||||
} else {
|
||||
this.products.put(product, count);
|
||||
}
|
||||
}
|
||||
|
||||
public void setProducts(Map<String, Quantity> products) {
|
||||
public void setProducts(Map<Product, Quantity> products) {
|
||||
this.products = products;
|
||||
}
|
||||
public void setMinimumTimePeriod(int timePeriod) {
|
||||
this.minimumTimePeriod = timePeriod;
|
||||
}
|
||||
|
||||
public void setTotalCost(int totalCost) {
|
||||
public void setTotalCost(MonetaryAmount totalCost) {
|
||||
this.totalCost = totalCost;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
// SPDX-FileCopyrightText: 2023 swt23w23
|
||||
// SPDX-FileCopyrightText: 2023-2024 swt23w23
|
||||
package catering.orderCatalog;
|
||||
|
||||
import catering.order.OrderType;
|
||||
|
@ -7,43 +7,40 @@ import org.salespointframework.catalog.Product;
|
|||
import org.salespointframework.core.DataInitializer;
|
||||
import org.salespointframework.quantity.Quantity;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.salespointframework.inventory.UniqueInventory;
|
||||
import org.salespointframework.inventory.UniqueInventoryItem;
|
||||
|
||||
import javax.money.CurrencyUnit;
|
||||
import javax.money.Monetary;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.javamoney.moneta.Money;
|
||||
|
||||
@Component
|
||||
public class CustomCatalogEntryDataInitializer implements DataInitializer {
|
||||
private CustomCatalogEntryRepository catalogEntryRepository;
|
||||
private final UniqueInventory<UniqueInventoryItem> inventory;
|
||||
|
||||
public CustomCatalogEntryDataInitializer(CustomCatalogEntryRepository catalogEntryRepository) {
|
||||
public CustomCatalogEntryDataInitializer(CustomCatalogEntryRepository catalogEntryRepository, UniqueInventory<UniqueInventoryItem> inventory) {
|
||||
this.catalogEntryRepository = catalogEntryRepository;
|
||||
this.inventory = inventory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
|
||||
Map<Product, Quantity> products = new HashMap<>();
|
||||
CurrencyUnit currencyUnit = Monetary.getCurrency("EUR");
|
||||
products.put(new Product("Brötchen", Monetary.getDefaultAmountFactory()
|
||||
.setCurrency(currencyUnit)
|
||||
.setNumber(1)
|
||||
.create()), Quantity.of(30));
|
||||
products.put(new Product("Kerze", Monetary.getDefaultAmountFactory()
|
||||
.setCurrency(currencyUnit)
|
||||
.setNumber(2)
|
||||
.create()), Quantity.of(20));
|
||||
Product product1 = inventory.findAll().stream().toList().get(0).getProduct();
|
||||
Product product2 = inventory.findAll().stream().toList().get(1).getProduct();
|
||||
Product product3 = inventory.findAll().stream().toList().get(2).getProduct();
|
||||
|
||||
products.put(product1, product1.createQuantity(30));
|
||||
products.put(product2, product2.createQuantity(15));
|
||||
products.put(product3, product3.createQuantity(1));
|
||||
|
||||
Map<String, Quantity> productsFormatted = new HashMap<String, Quantity>();
|
||||
for (Product product : products.keySet()) {
|
||||
productsFormatted.put(product.getName(), products.get(product));
|
||||
}
|
||||
catalogEntryRepository.save(
|
||||
new CustomCatalogEntry(
|
||||
OrderType.EVENT_CATERING,
|
||||
productsFormatted,
|
||||
4,
|
||||
500));
|
||||
products,
|
||||
Money.of(500, "EUR")));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,16 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
// SPDX-FileCopyrightText: 2023 swt23w23
|
||||
// SPDX-FileCopyrightText: 2023-2024 swt23w23
|
||||
package catering.orderCatalog;
|
||||
|
||||
import org.salespointframework.catalog.Product;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
import org.springframework.data.util.Streamable;
|
||||
|
||||
interface CustomCatalogEntryRepository extends CrudRepository<CustomCatalogEntry, Long> {
|
||||
public interface CustomCatalogEntryRepository extends CrudRepository<CustomCatalogEntry, Long> {
|
||||
@Override
|
||||
Streamable<CustomCatalogEntry> findAll();
|
||||
|
||||
@Query("SELECT entry FROM CustomCatalogEntry entry JOIN entry.products p WHERE KEY(p) = :product")
|
||||
Streamable<CustomCatalogEntry> findByProduct(Product product);
|
||||
}
|
||||
|
|
|
@ -14,22 +14,16 @@ SPDX-FileCopyrightText: 2023-2024 swt23w23
|
|||
<div>
|
||||
<table class="table">
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>Name</th>
|
||||
<th>Mindestzeitraum</th>
|
||||
<th>Eventtyp</th>
|
||||
<th>Basisausstattung</th>
|
||||
<th>Preis ab</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
<tr th:each="catalogEntry : ${catalogEntries}">
|
||||
<td>
|
||||
**BILD**
|
||||
</td>
|
||||
<td th:text="${catalogEntry.getEventType()}">
|
||||
<td th:text="${catalogEntry.getMinimumTimePeriod()} + ' h'">
|
||||
<td th:text="${catalogEntry.eventType.toHumanReadable()}">
|
||||
<td>
|
||||
<ul th:each="product : ${catalogEntry.getProducts()}">
|
||||
<li th:text="${product.getKey().toString()} + ': ' + ${product.getValue().toString()}"/>
|
||||
<li th:text="${product.getKey().getName()} + ': ' + ${product.getValue().toString()}"/>
|
||||
</ul>
|
||||
</td>
|
||||
<td th:text="${catalogEntry.getTotalCost()}">
|
||||
|
@ -39,6 +33,13 @@ SPDX-FileCopyrightText: 2023-2024 swt23w23
|
|||
<button class="btn btn-danger" type="submit">Entfernen</button>
|
||||
</form>
|
||||
</td>
|
||||
<td>
|
||||
<form method="post" sec:authorize="hasRole('CUSTOMER')" th:action="@{/catalog/addToCart}">
|
||||
<input type="hidden" name="catalogEntryID" th:value="${catalogEntry.getId()}">
|
||||
<button class="btn btn-primary" type="submit">Zum Eventplaner hinzufügen</button>
|
||||
</form>
|
||||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
|
|
@ -13,27 +13,15 @@ SPDX-FileCopyrightText: 2023-2024 swt23w23
|
|||
<input type="hidden" name="addCatalog">
|
||||
<div class="content">
|
||||
<h2>Dienstleistung</h2>
|
||||
<label class="form-label" for="events"></label>
|
||||
<form th:object="${formCatalogEntry}" method="post" th:action="@{/catalog_editor/chooseEvent}">
|
||||
<select class="form-select w-auto d-inline-block" name="events" id="events">
|
||||
<option value="event_catering">Eventcatering</option>
|
||||
<option value="mobile_breakfast">Mobile Breakfast</option>
|
||||
<option value="rent_a_cook">Rent-a-Cook</option>
|
||||
<form class="my-4" th:object="${formCatalogEntry}" method="post" th:action="@{/catalog_editor/chooseEvent}">
|
||||
<select class="form-select w-auto d-inline-block" name="eventType">
|
||||
<option th:selected="${formCatalogEntry.getEventType().toString() == enumValue.toString()}" th:each="enumValue : ${T(catering.order.OrderType).values()}" th:value="${enumValue.toString()}" th:text="${enumValue.toHumanReadable()}"/>
|
||||
</select>
|
||||
<button class="btn btn-secondary" type="submit">Event auswählen</button>
|
||||
</form>
|
||||
Eventbasispreis: EUR 500
|
||||
|
||||
<h2>Mindestzeitraum</h2>
|
||||
<form th:object="${formCatalogEntry}" method="post" th:action="@{/catalog_editor/addTime}">
|
||||
<label class="form-label">Mindestzeitraum:</label>
|
||||
<input type="hidden" th:field="*{eventType}">
|
||||
<input class="form-control w-auto d-inline-block" th:field="*{minimumTimePeriod}" type="number" min="0" step="1" value="1"/>
|
||||
<button class="btn btn-secondary" type="submit">Zum Model hinzufügen</button>
|
||||
</form>
|
||||
|
||||
<h2>Basisausstattung</h2>
|
||||
<table class="table">
|
||||
<table class="table my-4">
|
||||
<tr>
|
||||
<th>Produktname</th>
|
||||
<th>Menge</th>
|
||||
|
@ -51,15 +39,37 @@ SPDX-FileCopyrightText: 2023-2024 swt23w23
|
|||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<h2>Produktauswahl</h2>
|
||||
<table class="table">
|
||||
<h2 class="mb-4">Produktauswahl</h2>
|
||||
<h3>Verbrauchsgegenstände</h3>
|
||||
<table class="table my-4">
|
||||
<tr>
|
||||
<th>Produktname</th>
|
||||
<th>Kosten</th>
|
||||
<th>Verfügbar</th>
|
||||
<th>Menge</th>
|
||||
</tr>
|
||||
<tr th:each="item : ${inventory}">
|
||||
<tr th:each="item : ${inventory}" th:if="${item.getProduct().getClass().simpleName == 'Consumable'}">
|
||||
<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="@{/catalog_editor/addProduct}" method="post">
|
||||
<input id="number" type="number" name="number" min="1" 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>
|
||||
<h3>Mietgegenstände</h3>
|
||||
<table class="table my-4">
|
||||
<tr>
|
||||
<th>Produktname</th>
|
||||
<th>Kosten</th>
|
||||
<th>Verfügbar</th>
|
||||
<th>Menge</th>
|
||||
</tr>
|
||||
<tr th:each="item : ${inventory}" th:if="${item.getProduct().getClass().simpleName == 'Rentable'}">
|
||||
<td th:text="${item.getProduct().getName()}">Name</td>
|
||||
<td th:text="${item.getProduct().getPrice()}">Preis</td>
|
||||
<td th:text="${item.getQuantity()}">Verfügbar</td>
|
||||
|
@ -72,16 +82,14 @@ SPDX-FileCopyrightText: 2023-2024 swt23w23
|
|||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<br>
|
||||
<h3>Momentane Auswahl</h3>
|
||||
Eventtyp: <span th:text="${formCatalogEntry.getEventType()}"></span><br>
|
||||
Mindestzeitraum: <span th:text="${formCatalogEntry.getMinimumTimePeriod()} + ' h'"></span><br>
|
||||
Eventtyp: <span th:text="${formCatalogEntry.getEventType().toHumanReadable()}"></span>
|
||||
<br>
|
||||
<span th:text="'Gesamtpreis: ' + ${formCatalogEntry.getTotalCost()}">Gesamtpreis</span>
|
||||
<form method="post" th:action="@{/catalog_editor/addCatalogEntry}" th:object="${formCatalogEntry}">
|
||||
<input type="hidden" name="eventType" th:value="${formCatalogEntry.getEventType()}">
|
||||
<input type="hidden" name="products" th:value="${productSet}">
|
||||
<input type="hidden" name="minimumTimePeriod" th:value="${formCatalogEntry.getMinimumTimePeriod}">
|
||||
<input type="hidden" name="totalCost" th:value="${formCatalogEntry.getTotalCost()}">
|
||||
<input type="hidden" name="totalCost" th:value="${formCatalogEntry.getTotalCost().getNumber().doubleValueExact()}">
|
||||
<button class="btn btn-primary" type="submit">Zum Katalog hinzufügen</button>
|
||||
</form>
|
||||
</div>
|
||||
|
|
|
@ -25,6 +25,7 @@ import java.math.BigDecimal;
|
|||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
import catering.orderCatalog.CustomCatalogEntryRepository;
|
||||
import org.javamoney.moneta.Money;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
@ -60,6 +61,9 @@ class InventoryControllerIntegrationTests {
|
|||
@Autowired
|
||||
CateringCatalog catalog;
|
||||
|
||||
@Autowired
|
||||
private CustomCatalogEntryRepository catalogEntryRepository;
|
||||
|
||||
UniqueInventoryItem anyConsumableItem;
|
||||
UniqueInventoryItem anyRentableItem;
|
||||
Consumable anyConsumable;
|
||||
|
@ -101,6 +105,7 @@ class InventoryControllerIntegrationTests {
|
|||
|
||||
@BeforeEach
|
||||
void populateAnyInventoryItem() {
|
||||
catalogEntryRepository.deleteAll();
|
||||
inventory.deleteAll();
|
||||
catalog.deleteAll();
|
||||
|
||||
|
|
|
@ -0,0 +1,98 @@
|
|||
package catering.orderCatalog;
|
||||
|
||||
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrl;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.javamoney.moneta.Money;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.salespointframework.catalog.Product;
|
||||
import org.salespointframework.inventory.UniqueInventory;
|
||||
import org.salespointframework.inventory.UniqueInventoryItem;
|
||||
import org.salespointframework.quantity.Quantity;
|
||||
import org.salespointframework.useraccount.Password;
|
||||
import org.salespointframework.useraccount.Role;
|
||||
import org.salespointframework.useraccount.UserAccountManagement;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.security.test.context.support.WithMockUser;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
|
||||
import catering.order.OrderType;
|
||||
|
||||
@SpringBootTest
|
||||
@AutoConfigureMockMvc
|
||||
public class CatalogControllerIntegrationTests {
|
||||
|
||||
@Autowired
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@Autowired
|
||||
private CatalogController catalogController;
|
||||
|
||||
@Autowired
|
||||
UserAccountManagement userAccountManagement;
|
||||
|
||||
@Autowired
|
||||
private CustomCatalogEntryRepository catalogEntryRepository;
|
||||
|
||||
@Autowired
|
||||
private UniqueInventory<UniqueInventoryItem> inventory;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
if (userAccountManagement.findByUsername("anna").isEmpty()) {
|
||||
userAccountManagement.create("anna",
|
||||
Password.UnencryptedPassword.of("12345"), Role.of("CUSTOMER"));
|
||||
}
|
||||
|
||||
if (catalogEntryRepository.findAll().isEmpty()) {
|
||||
Map<Product, Quantity> products = new HashMap<>();
|
||||
products.put(inventory.findAll().stream().toList().get(0).getProduct(), Quantity.of(1));
|
||||
|
||||
CustomCatalogEntry testCatalogEntry = new CustomCatalogEntry(
|
||||
OrderType.RENT_A_COOK,
|
||||
products,
|
||||
Money.of(3000, "EUR"));
|
||||
catalogEntryRepository.save(testCatalogEntry);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCustomerViewsCatalog() throws Exception {
|
||||
this.mockMvc.perform(get("/catalog").with(user("anna").roles("CUSTOMER")))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(view().name("catalog"))
|
||||
.andExpect(model().attributeExists("catalogEntries"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockUser(username = "admin", roles = "ADMIN")
|
||||
void testAddCatalogEntry() throws Exception {
|
||||
this.mockMvc.perform(post("/catalog_editor/addCatalogEntry")
|
||||
.param("eventType", "MOBILE_BREAKFAST")
|
||||
.param("totalCost", "5000"))
|
||||
.andExpect(redirectedUrl("/catalog"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockUser(username = "admin", roles = "ADMIN")
|
||||
void testRemoveCatalogEntry() throws Exception {
|
||||
this.mockMvc.perform(post("/catalog/remove")
|
||||
.param("catalogEntryID",
|
||||
String.valueOf(catalogEntryRepository.findAll()
|
||||
.stream().toList()
|
||||
.get(0)
|
||||
.getId())))
|
||||
.andExpect(redirectedUrl("/catalog"));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
package catering.orderCatalog;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.javamoney.moneta.Money;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.salespointframework.catalog.Product;
|
||||
import org.salespointframework.inventory.UniqueInventory;
|
||||
import org.salespointframework.inventory.UniqueInventoryItem;
|
||||
import org.salespointframework.quantity.Quantity;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
import catering.order.OrderType;
|
||||
|
||||
@SpringBootTest
|
||||
public class CatalogControllerUnitTests {
|
||||
|
||||
@Autowired
|
||||
CustomCatalogEntryRepository catalogEntryRepository;
|
||||
|
||||
@Autowired
|
||||
UniqueInventory<UniqueInventoryItem> inventory;
|
||||
|
||||
@BeforeEach
|
||||
void setup() {
|
||||
Product product1 = inventory.findAll().stream().toList().get(0).getProduct();
|
||||
Map<Product, Quantity> products = new HashMap<Product, Quantity>();
|
||||
products.put(product1, Quantity.of(1));
|
||||
|
||||
CustomCatalogEntry catalogEntry1 = new CustomCatalogEntry(
|
||||
OrderType.EVENT_CATERING,
|
||||
products,
|
||||
Money.of(0, "EUR"));
|
||||
|
||||
catalogEntryRepository.save(catalogEntry1);
|
||||
}
|
||||
|
||||
@Test
|
||||
void countOfEntries() {
|
||||
// Includes entry of data initializer
|
||||
assertThat(catalogEntryRepository.findAll().stream().count()).isEqualTo(2);
|
||||
}
|
||||
}
|
61
src/test/java/catering/orderCatalog/CatalogUnitTests.java
Normal file
61
src/test/java/catering/orderCatalog/CatalogUnitTests.java
Normal file
|
@ -0,0 +1,61 @@
|
|||
package catering.orderCatalog;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.javamoney.moneta.Money;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.salespointframework.catalog.Product;
|
||||
import org.salespointframework.inventory.UniqueInventory;
|
||||
import org.salespointframework.inventory.UniqueInventoryItem;
|
||||
import org.salespointframework.quantity.Quantity;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
import catering.order.OrderType;
|
||||
|
||||
@SpringBootTest
|
||||
public class CatalogUnitTests {
|
||||
|
||||
@Autowired
|
||||
CustomCatalogEntryRepository catalogEntryRepository;
|
||||
|
||||
@Autowired
|
||||
UniqueInventory<UniqueInventoryItem> inventory;
|
||||
|
||||
private CustomCatalogEntry catalogEntry;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
Product product1 = inventory.findAll().stream().toList().get(0).getProduct();
|
||||
Map<Product, Quantity> products = new HashMap<Product, Quantity>();
|
||||
products.put(product1, Quantity.of(1));
|
||||
|
||||
this.catalogEntry = new CustomCatalogEntry(
|
||||
OrderType.EVENT_CATERING,
|
||||
products,
|
||||
Money.of(0, "EUR"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testAddProduct() {
|
||||
catalogEntry.addProduct(inventory.findAll().stream().toList().get(0).getProduct(), Quantity.of(1));
|
||||
assertTrue(catalogEntry.getProducts().containsValue(Quantity.of(2)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSetEventType() {
|
||||
catalogEntry.setEventType(OrderType.PARTY_SERVICE);
|
||||
assertTrue(catalogEntry.getEventType().equals(OrderType.PARTY_SERVICE));
|
||||
}
|
||||
|
||||
// Getter is being tested because it calculates totalCost before
|
||||
@Test
|
||||
void testGetTotalCost() {
|
||||
assertTrue(inventory.findAll().stream().toList().get(0).getProduct().getPrice()
|
||||
.equals(catalogEntry.getTotalCost()));
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue