mirror of
https://github.com/st-tu-dresden-praktikum/swt23w23
synced 2024-07-19 21:04:36 +02:00
Associate rentables with order and event explicitly
This closes #74 Co-authored-by: Theo Reichert <theo.reichert@mailbox.tu-dresden.de>
This commit is contained in:
parent
cef94a0bdb
commit
34c7c96c70
|
@ -19,11 +19,14 @@ package catering.catalog;
|
|||
import org.salespointframework.catalog.Catalog;
|
||||
import org.salespointframework.catalog.Product;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.util.Streamable;
|
||||
import org.springframework.lang.NonNull;
|
||||
|
||||
import catering.order.OrderType;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public interface CateringCatalog extends Catalog<Product> {
|
||||
static final Sort DEFAULT_SORT = Sort.sort(Product.class).by(Product::getName).ascending();
|
||||
|
||||
|
@ -46,8 +49,14 @@ public interface CateringCatalog extends Catalog<Product> {
|
|||
return findByCategories(category, DEFAULT_SORT);
|
||||
}
|
||||
|
||||
Streamable<Product> findRentablesByCategories(@NonNull String category);
|
||||
@Query("select p from #{#entityName} p")
|
||||
Streamable<Rentable> findRentables();
|
||||
|
||||
Streamable<Product> findConsumablesByCategories(@NonNull String category);
|
||||
@Query("select p from #{#entityName} p")
|
||||
Streamable<Consumable> findConsumables();
|
||||
|
||||
Streamable<Rentable> findRentablesByCategoriesContains(@NonNull String category);
|
||||
|
||||
Streamable<Consumable> findConsumablesByCategoriesContains(@NonNull String category);
|
||||
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ import jakarta.persistence.Entity;
|
|||
public class Rentable extends Product {
|
||||
|
||||
private MonetaryAmount wholesalePrice;
|
||||
private MonetaryAmount pricePerHour;
|
||||
|
||||
@SuppressWarnings({ "deprecation" })
|
||||
public Rentable() {
|
||||
|
@ -41,4 +42,8 @@ public class Rentable extends Product {
|
|||
public MonetaryAmount getRetailPrice() {
|
||||
return super.getPrice();
|
||||
}
|
||||
|
||||
public MonetaryAmount getPriceForTime(int hours) {
|
||||
return getPrice().multiply(hours).add(getPrice());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,13 @@
|
|||
package catering.order;
|
||||
|
||||
import catering.catalog.Rentable;
|
||||
import catering.staff.Employee;
|
||||
import org.javamoney.moneta.Money;
|
||||
import org.salespointframework.inventory.UniqueInventory;
|
||||
import org.salespointframework.inventory.UniqueInventoryItem;
|
||||
import org.salespointframework.order.Cart;
|
||||
import org.salespointframework.order.CartItem;
|
||||
import org.salespointframework.order.OrderLine;
|
||||
|
||||
import javax.money.MonetaryAmount;
|
||||
import java.time.Duration;
|
||||
|
@ -63,6 +68,31 @@ public class CustomCart extends Cart {
|
|||
return order;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add ChargeLines for rental costs of each Rentable to {@param order}
|
||||
*/
|
||||
public CustomOrder addRentablesToOrder(CustomOrder order, UniqueInventory<UniqueInventoryItem> inventory) {
|
||||
for (CartItem item : this) {
|
||||
if (item.getProduct() instanceof Rentable rentable) {
|
||||
OrderLine orderLine = order.getOrderLines(rentable).stream().findFirst().get();
|
||||
|
||||
order.addChargeLine(
|
||||
rentable.getPrice()
|
||||
.multiply(getDurationInHours())
|
||||
.multiply(item.getQuantity().getAmount()),
|
||||
"rental costs",
|
||||
orderLine
|
||||
);
|
||||
|
||||
|
||||
// neutralises automatic reduction of rentables in inventory
|
||||
inventory.save(inventory.findByProduct(rentable).get().increaseQuantity(orderLine.getQuantity()));
|
||||
}
|
||||
}
|
||||
|
||||
return order;
|
||||
}
|
||||
|
||||
public OrderType getOrderType() {
|
||||
return orderType;
|
||||
}
|
||||
|
@ -80,10 +110,10 @@ public class CustomCart extends Cart {
|
|||
}
|
||||
|
||||
/**
|
||||
* @return hours between start and finish multiplied with a rate
|
||||
* @return hours between start and finish
|
||||
*/
|
||||
public double getDurationInHoursTimesRate(double rate) {
|
||||
return (float) Duration.between(start, finish).getSeconds() / 3600 * rate;
|
||||
public int getDurationInHours() {
|
||||
return (int) (Duration.between(start, finish).getSeconds() / 3600);
|
||||
}
|
||||
|
||||
public LocalDateTime getFinish() {
|
||||
|
@ -100,14 +130,19 @@ public class CustomCart extends Cart {
|
|||
|
||||
@Override
|
||||
public MonetaryAmount getPrice() {
|
||||
MonetaryAmount total = super.getPrice();
|
||||
MonetaryAmount total = Money.of(0, "EUR");
|
||||
|
||||
for (int i = 0; i < staff.size(); i++) { // TODO: get this from employee itself
|
||||
total = total.add(Money.of(getDurationInHoursTimesRate(12.0), "EUR"));
|
||||
for (CartItem item : this) {
|
||||
if (item.getProduct() instanceof Rentable rentable) {
|
||||
// final_price = (price + price * time) * quantity
|
||||
total = total.add(rentable.getPriceForTime(getDurationInHours()).multiply(item.getQuantity().getAmount()));
|
||||
} else {
|
||||
total = total.add(item.getProduct().getPrice().multiply(item.getQuantity().getAmount()));
|
||||
}
|
||||
}
|
||||
|
||||
for (Employee employee : staff) {
|
||||
total = total.add(Money.of(getDurationInHoursTimesRate(12), "EUR")); // TODO: get from employee
|
||||
total = total.add(Money.of(getDurationInHours() * employee.getWage(), "EUR"));
|
||||
}
|
||||
|
||||
return total;
|
||||
|
|
|
@ -22,7 +22,7 @@ public class CustomOrder extends Order {
|
|||
private Long id;
|
||||
@ManyToMany
|
||||
private Set<Employee> staff;
|
||||
private OrderType orderType = OrderType.SOMETHING_ELSE;
|
||||
private OrderType orderType = OrderType.EVENT_CATERING;
|
||||
private LocalDateTime start;
|
||||
private LocalDateTime finish;
|
||||
private boolean invoiceAvailable = false;
|
||||
|
@ -44,7 +44,7 @@ public class CustomOrder extends Order {
|
|||
* Helper function to get the amount of hours in between start and finish (analogous to CustomCart)
|
||||
* @return hours between start and finish
|
||||
*/
|
||||
private long getDurationInHours(LocalDateTime start, LocalDateTime finish) {
|
||||
public long getDurationInHours() {
|
||||
return Duration.between(start, finish).getSeconds() / 3600;
|
||||
}
|
||||
|
||||
|
@ -52,8 +52,8 @@ public class CustomOrder extends Order {
|
|||
* Adds an employee to the order and adds a new {@Link ChangeLine} containing the costs
|
||||
*/
|
||||
public boolean addEmployee(Employee employee) {
|
||||
MonetaryAmount cost = Money.of(12.0, "EUR")
|
||||
.multiply(getDurationInHours(this.start, this.finish)); // TODO: Get salary from employee
|
||||
MonetaryAmount cost = Money.of(employee.getWage(), "EUR")
|
||||
.multiply(getDurationInHours());
|
||||
|
||||
if (this.staff.add(employee)) {
|
||||
super.addChargeLine(cost, employee.getId().toString());
|
||||
|
|
24
src/main/java/catering/order/CustomOrderRepository.java
Normal file
24
src/main/java/catering/order/CustomOrderRepository.java
Normal file
|
@ -0,0 +1,24 @@
|
|||
package catering.order;
|
||||
|
||||
import catering.catalog.Rentable;
|
||||
import org.salespointframework.inventory.UniqueInventory;
|
||||
import org.salespointframework.inventory.UniqueInventoryItem;
|
||||
import org.salespointframework.order.Order;
|
||||
import org.salespointframework.quantity.Quantity;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.util.Streamable;
|
||||
import org.springframework.data.repository.Repository;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
public interface CustomOrderRepository extends Repository<CustomOrder, Order.OrderIdentifier>{
|
||||
|
||||
@Query("""
|
||||
select order from #{#entityName} order
|
||||
where
|
||||
not order.start > ?2 and
|
||||
not order.finish < ?1
|
||||
""")
|
||||
Streamable<CustomOrder> findOrdersByInterval(LocalDateTime start, LocalDateTime finish);
|
||||
|
||||
}
|
|
@ -1,5 +1,8 @@
|
|||
package catering.order;
|
||||
|
||||
import catering.catalog.CateringCatalog;
|
||||
import catering.catalog.Consumable;
|
||||
import catering.catalog.Rentable;
|
||||
import catering.staff.Employee;
|
||||
import catering.staff.StaffManagement;
|
||||
import org.salespointframework.catalog.Product;
|
||||
|
@ -11,7 +14,6 @@ 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.data.util.Streamable;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
|
@ -31,11 +33,15 @@ import java.util.stream.Collectors;
|
|||
public class OrderController {
|
||||
|
||||
private final OrderManagement<CustomOrder> orderManagement;
|
||||
private final CustomOrderRepository customOrderRepository;
|
||||
private final UniqueInventory<UniqueInventoryItem> inventory;
|
||||
private final CateringCatalog catalog;
|
||||
private final StaffManagement staffManagement;
|
||||
|
||||
public OrderController(OrderManagement<CustomOrder> orderManagement, UniqueInventory<UniqueInventoryItem> inventory, StaffManagement staffManagement) {
|
||||
public OrderController(OrderManagement<CustomOrder> orderManagement, CustomOrderRepository customOrderRepository, UniqueInventory<UniqueInventoryItem> inventory, CateringCatalog catalog, StaffManagement staffManagement) {
|
||||
this.orderManagement = orderManagement;
|
||||
this.customOrderRepository = customOrderRepository;
|
||||
this.catalog = catalog;
|
||||
this.inventory = inventory;
|
||||
this.staffManagement = staffManagement;
|
||||
}
|
||||
|
@ -71,11 +77,9 @@ public class OrderController {
|
|||
// Obtains an instance of LocalDate from a text string such as 2007-12-03.
|
||||
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());
|
||||
List<CustomOrder> myOrders = customOrderRepository.findOrdersByInterval(date.atStartOfDay(),
|
||||
date.atStartOfDay().plusHours(23).withMinute(59).withSecond(59))
|
||||
.stream().toList();
|
||||
|
||||
model.addAttribute("orders", myOrders);
|
||||
model.addAttribute("total", myOrders.size());
|
||||
|
@ -84,19 +88,45 @@ public class OrderController {
|
|||
|
||||
@ModelAttribute("event")
|
||||
CustomCart initializeCart() {
|
||||
return new CustomCart(OrderType.SOMETHING_ELSE, LocalDateTime.now().plusDays(7),
|
||||
LocalDateTime.now().plusDays(7));
|
||||
return new CustomCart(OrderType.EVENT_CATERING, LocalDateTime.now().plusDays(7),
|
||||
LocalDateTime.now().plusDays(7).plusHours(1));
|
||||
}
|
||||
|
||||
@GetMapping("/event")
|
||||
@PreAuthorize("hasRole('CUSTOMER')")
|
||||
public String event(Model model, @ModelAttribute("event") CustomCart cart) {
|
||||
model.addAttribute("items", cart.stream().collect(Collectors.toList()));
|
||||
|
||||
model.addAttribute("cartRentables", cart.stream().filter(item -> item.getProduct() instanceof Rentable).toList());
|
||||
|
||||
model.addAttribute("cartConsumables", cart.stream().filter(item -> item.getProduct() instanceof Consumable).toList());
|
||||
|
||||
model.addAttribute("totalPrice", cart.getPrice());
|
||||
model.addAttribute("invItems", inventory.findAll().stream().collect(Collectors.toList()));
|
||||
Set<Employee> myStaff = new HashSet<>();
|
||||
staffManagement.findAll().forEach(myStaff::add);
|
||||
model.addAttribute("allStaff", myStaff);
|
||||
|
||||
Map<Consumable, Quantity> invConsumables = new HashMap<>();
|
||||
catalog.findConsumablesByCategoriesContains(cart.getOrderType().toString()).forEach(consumable ->
|
||||
invConsumables.put(
|
||||
consumable,
|
||||
inventory.findByProduct(consumable).get().getQuantity())
|
||||
);
|
||||
|
||||
model.addAttribute("invConsumables", invConsumables);
|
||||
|
||||
model.addAttribute(
|
||||
"invRentables",
|
||||
catalog.findRentablesByCategoriesContains(cart.getOrderType().toString())
|
||||
.stream()
|
||||
.collect(Collectors.toMap(rentable -> rentable, rentable -> findFreeAmountInInterval(
|
||||
rentable,
|
||||
cart.getStart(),
|
||||
cart.getFinish(),
|
||||
inventory,
|
||||
customOrderRepository))));
|
||||
|
||||
model.addAttribute("allStaff", staffManagement.findAll().stream().toList());
|
||||
|
||||
model.addAttribute("duration", cart.getDurationInHours());
|
||||
|
||||
model.addAttribute("minDate", LocalDate.now().plusDays(7));
|
||||
|
||||
return "event";
|
||||
}
|
||||
|
@ -140,14 +170,24 @@ public class OrderController {
|
|||
@PostMapping("/event/addProduct")
|
||||
@PreAuthorize("hasRole('CUSTOMER')")
|
||||
public String addProduct(@RequestParam("pid") Product product, @RequestParam("number") int number, @ModelAttribute("event") CustomCart cart) {
|
||||
|
||||
Quantity amount = Quantity.of(number > 0 ? number : 1);
|
||||
Quantity invAmount = inventory.findByProduct(product).get().getQuantity(); // TODO ERROR HANDLING
|
||||
Quantity cartQuantity = cart.getQuantity(product);
|
||||
Quantity available;
|
||||
|
||||
if (product instanceof Rentable rentable) {
|
||||
available = findFreeAmountInInterval(
|
||||
rentable,
|
||||
cart.getStart(),
|
||||
cart.getFinish(),
|
||||
inventory,
|
||||
customOrderRepository);
|
||||
} else {
|
||||
available = inventory.findByProduct(product).get().getQuantity();
|
||||
}
|
||||
|
||||
// check for possible miss-inputs
|
||||
if (amount.add(cartQuantity).isGreaterThan(invAmount)) {
|
||||
cart.addOrUpdateItem(product, cartQuantity.negate().add(invAmount));
|
||||
if (amount.add(cartQuantity).isGreaterThan(available)) {
|
||||
cart.addOrUpdateItem(product, cartQuantity.negate().add(available));
|
||||
} else {
|
||||
cart.addOrUpdateItem(product, amount);
|
||||
}
|
||||
|
@ -174,7 +214,7 @@ public class OrderController {
|
|||
LocalDateTime startTime = LocalDateTime.of(start, LocalTime.of(unwrappedStartHour, 0));
|
||||
LocalDateTime finishTime = LocalDateTime.of(finish,
|
||||
LocalTime.of(unwrappedFinishHour <= unwrappedStartHour
|
||||
&& !finish.isAfter(start) ? unwrappedStartHour+1 : unwrappedFinishHour, 0));
|
||||
&& !finish.isAfter(start) ? (unwrappedStartHour+1) % 24 : unwrappedFinishHour, 0));
|
||||
|
||||
cart.setStart(startTime);
|
||||
cart.setFinish(finishTime);
|
||||
|
@ -193,7 +233,8 @@ public class OrderController {
|
|||
CustomOrder myOrder = new CustomOrder(account.getId(), cart);
|
||||
cart.addItemsTo(myOrder);
|
||||
cart.addStaffTo(myOrder);
|
||||
orderManagement.payOrder(myOrder); // TODO: change this later
|
||||
cart.addRentablesToOrder(myOrder, inventory);
|
||||
orderManagement.payOrder(myOrder);
|
||||
orderManagement.completeOrder(myOrder);
|
||||
cart.clear();
|
||||
|
||||
|
@ -203,27 +244,26 @@ public class OrderController {
|
|||
|
||||
@PostMapping("/event/changeOrderType")
|
||||
@PreAuthorize("hasRole('CUSTOMER')")
|
||||
public String changeOrderType(@RequestParam(name = "type") Optional<String> optionalOrderType, @ModelAttribute("event") CustomCart cart) {
|
||||
String orderType = optionalOrderType.orElse("FOO");
|
||||
switch (orderType) {
|
||||
case "RaK":
|
||||
cart.setOrderType(OrderType.RENT_A_COOK);
|
||||
break;
|
||||
case "EK":
|
||||
cart.setOrderType(OrderType.EVENT_CATERING);
|
||||
break;
|
||||
case "SN":
|
||||
cart.setOrderType(OrderType.SUSHI_NIGHT);
|
||||
break;
|
||||
case "MB":
|
||||
cart.setOrderType(OrderType.MOBILE_BREAKFAST);
|
||||
break;
|
||||
default:
|
||||
cart.setOrderType(OrderType.SOMETHING_ELSE);
|
||||
public String changeOrderType(@RequestParam(name = "type") String orderType, @ModelAttribute("event") CustomCart cart) {
|
||||
try {
|
||||
cart.setOrderType(OrderType.valueOf(orderType));
|
||||
} catch (IllegalArgumentException e) {
|
||||
cart.setOrderType(OrderType.EVENT_CATERING);
|
||||
}
|
||||
return "redirect:/event";
|
||||
}
|
||||
|
||||
public static Quantity findFreeAmountInInterval(Rentable product, LocalDateTime start, LocalDateTime finish, UniqueInventory<UniqueInventoryItem> inventory, CustomOrderRepository customOrderRepository) {
|
||||
|
||||
return inventory.findByProduct(product)
|
||||
.map(item -> item.getQuantity().subtract(
|
||||
customOrderRepository.findOrdersByInterval(start, finish)
|
||||
.flatMap(order -> order.getOrderLines(product).stream())
|
||||
.map(OrderLine::getQuantity).stream()
|
||||
.reduce(Quantity.NONE, Quantity::add)))
|
||||
.orElse(Quantity.NONE);
|
||||
}
|
||||
|
||||
@GetMapping("/orders/calender")
|
||||
public String calender(Model model) {
|
||||
ArrayList<ArrayList<String>> datesOfMonth = new ArrayList<ArrayList<String>>(28);
|
||||
|
@ -232,7 +272,7 @@ public class OrderController {
|
|||
LocalDate startDate = startDateTime.toLocalDate();
|
||||
LocalDate endDate = endDateTime.toLocalDate();
|
||||
|
||||
// create all dates of the calender
|
||||
// create all dates of the calendar
|
||||
for (LocalDate date = startDate; !date.isAfter(endDate); date = date.plusDays(1)) {
|
||||
ArrayList<String> x = new ArrayList<String>(2);
|
||||
x.add(Integer.toString(date.getDayOfMonth()));
|
||||
|
@ -240,19 +280,8 @@ public class OrderController {
|
|||
datesOfMonth.add(x);
|
||||
}
|
||||
|
||||
/*
|
||||
* FIXME: Do not load all orders into java,
|
||||
* instead query orderManagement better to only return orders overlapping with interval [startDate,endDate]
|
||||
* by using "query creation" of the jpa
|
||||
* e.g. this.orderManagement.findByFinishDateIsNotBeforeAndStartDateIsNotAfter(LocalDateTime startDateTime, LocalDateTime endDateTime)
|
||||
*/
|
||||
Streamable<CustomOrder> x = this.orderManagement.findAll(Pageable.unpaged()).filter(e ->
|
||||
!e.getFinish().toLocalDate().isBefore(startDate) && // end is not before today
|
||||
!e.getStart().toLocalDate().isAfter(endDate)
|
||||
);
|
||||
|
||||
// add each order overlapping with the calendar to the days it overlaps with
|
||||
for (CustomOrder order : x) {
|
||||
for (CustomOrder order : customOrderRepository.findOrdersByInterval(startDateTime, endDateTime)) {
|
||||
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;
|
||||
String order_id = Objects.requireNonNull(order.getId()).toString();
|
||||
|
|
|
@ -3,7 +3,16 @@ package catering.order;
|
|||
public enum OrderType {
|
||||
RENT_A_COOK,
|
||||
EVENT_CATERING,
|
||||
SUSHI_NIGHT,
|
||||
MOBILE_BREAKFAST,
|
||||
SOMETHING_ELSE
|
||||
PARTY_SERVICE;
|
||||
|
||||
public String toHumanReadable() {
|
||||
return switch (this) {
|
||||
case RENT_A_COOK -> "Miete einen Koch";
|
||||
case EVENT_CATERING -> "Veranstaltungsbewirtung";
|
||||
case MOBILE_BREAKFAST -> "Mobiles Frühstück";
|
||||
case PARTY_SERVICE -> "Sausedienst";
|
||||
default -> null;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -117,12 +117,6 @@ public class CatalogController {
|
|||
@PostMapping("/catalog_editor/chooseEvent")
|
||||
public String chooseEvent(String events) {
|
||||
switch (events) {
|
||||
case "event_catering":
|
||||
formCatalogEntry.setEventType(OrderType.EVENT_CATERING);
|
||||
break;
|
||||
case "sushi_night":
|
||||
formCatalogEntry.setEventType(OrderType.SUSHI_NIGHT);
|
||||
break;
|
||||
case "mobile_breakfast":
|
||||
formCatalogEntry.setEventType(OrderType.MOBILE_BREAKFAST);
|
||||
break;
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
<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="sushi_night">Sushi Night</option>
|
||||
<option value="mobile_breakfast">Mobile Breakfast</option>
|
||||
<option value="rent_a_cook">Rent-a-Cook</option>
|
||||
</select>
|
||||
|
|
|
@ -6,29 +6,21 @@
|
|||
|
||||
<body>
|
||||
<div layout:fragment="content">
|
||||
<form th:action="@{/event/changeOrderType}" method="post">
|
||||
<form class="my-4" th:action="@{/event/changeOrderType}" method="post">
|
||||
<select class="form-select w-auto d-inline-block" name="type">
|
||||
<option disabled="disabled" selected value="NULL" th:text="${event.getOrderType()}"/>
|
||||
<option th:value="'SE'" th:text="'Something else'"/>
|
||||
<option th:value="'RaK'" th:text="Rent-a-Cook"/>
|
||||
<option th:value="'EK'" th:text="Eventcatering"/>
|
||||
<option th:value="'SN'" th:text="'Sushi Night'"/>
|
||||
<option th:value="'MB'" th:text="'Mobile Breakfase'"/>
|
||||
<option th:selected="${event.getOrderType().toString() == enumValue.toString()}" th:each="enumValue : ${T(catering.order.OrderType).values()}" th:value="${enumValue.toString()}" th:text="${enumValue.toHumanReadable()}"/>
|
||||
</select>
|
||||
<button class="btn btn-primary" type="submit">Eventtypen ändern</button>
|
||||
</form>
|
||||
|
||||
<!-- I NEED SPACE -->
|
||||
<br>
|
||||
|
||||
<form th:action="@{/event/changeDate}" method="post">
|
||||
<form class="my-4" 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"/>
|
||||
<input type="date" th:value="${event.getStart().toLocalDate()}" th:min="${minDate}" 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"/>
|
||||
<input type="date" th:value="${event.getFinish().toLocalDate()}" th:min="${minDate}" 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>
|
||||
|
@ -36,20 +28,17 @@
|
|||
<button class="btn btn-primary" type="submit">Wunschdatum überprüfen</button>
|
||||
</form>
|
||||
|
||||
<!-- I NEED SPACE -->
|
||||
<br>
|
||||
|
||||
<table class="table">
|
||||
<table class="table my-4">
|
||||
<tr>
|
||||
<th>Produkt</th>
|
||||
<th>Anzahl</th>
|
||||
<th>Preis</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
<tr th:each="item : ${items}">
|
||||
<td th:text="${item.getProductName()}">Sake Nigiri</td>
|
||||
<td th:text="${item.getQuantity()}">200</td>
|
||||
<td th:text="${item.getPrice().getNumber().doubleValue()} +'€'">10€</td>
|
||||
<tr th:each="item : ${cartConsumables}">
|
||||
<td th:text="${item.getProductName()}"></td>
|
||||
<td th:text="${item.getQuantity()}"></td>
|
||||
<td th:text="${item.getPrice().getNumber().doubleValue()} +'€'"></td>
|
||||
<td>
|
||||
<form method="post" th:action="@{/event/removeProduct}">
|
||||
<input type="hidden" th:value="${item.getId()}" name="itemId"/>
|
||||
|
@ -57,14 +46,25 @@
|
|||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
<tr th:each="item : ${cartRentables}">
|
||||
<td th:text="${item.getProductName()}"></td>
|
||||
<td th:text="${item.getQuantity()}"></td>
|
||||
<td th:text="${item.getProduct().getPriceForTime(duration).multiply(item.getQuantity().getAmount())} +'€'"></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>
|
||||
<th>Angestellter</th>
|
||||
<th>Typ</th>
|
||||
<th>Preis</th>
|
||||
<th></th>
|
||||
<tr th:each="employee : ${event.getStaff()}">
|
||||
<td th:text="${employee.getName()}">Name</td>
|
||||
<td th:text="${employee.getJob()}">Job</td>
|
||||
<td th:text="${event.getDurationInHoursTimesRate(12.0)} + '€'">Preis</td> <!--TODO: get from employee-->
|
||||
<td th:text="${employee.getName()}"></td>
|
||||
<td th:text="${employee.getJob()}"></td>
|
||||
<td th:text="${event.getDurationInHours() * employee.getWage()} + '€'"></td>
|
||||
<td>
|
||||
<form method="post" th:action="@{/event/removeEmployee}">
|
||||
<input type="hidden" th:value="${employee.getId()}" name="sid"/>
|
||||
|
@ -74,41 +74,63 @@
|
|||
</tr>
|
||||
</table>
|
||||
|
||||
<span th:text="'Gesamt: ' + ${totalPrice}">Price</span>
|
||||
<span th:text="'Gesamt: ' + ${totalPrice.getNumber() + '€'}"></span>
|
||||
|
||||
<form method="post" th:action="@{/event/checkout}">
|
||||
<form class="py-4" method="post" th:action="@{/event/checkout}">
|
||||
<button class="btn btn-primary" type="submit">Kostenpflichtig bestellen</button>
|
||||
</form>
|
||||
|
||||
<!-- I NEED SPACE -->
|
||||
<br>
|
||||
<br>
|
||||
<h4>Verbrauchsgegenstand hinzufügen</h4>
|
||||
|
||||
<h4>Produkt hinzufügen</h4>
|
||||
|
||||
<table class="table">
|
||||
<table class="table my-4">
|
||||
<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>
|
||||
<tr th:each="item : ${invConsumables.entrySet()}">
|
||||
<td th:text="${item.getKey().getName()}"></td>
|
||||
<td th:text="${item.getKey().getPrice()}"></td>
|
||||
<td th:text="${item.getValue()}"></td>
|
||||
<td>
|
||||
<form th:action="@{/event/addProduct}" method="post">
|
||||
<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 id="number" type="number" name="number" min="1" th:max="${item.getValue()}" value="1"/>
|
||||
<input type="hidden" name="pid" th:value="${item.getKey().getId()}"/>
|
||||
<input class="btn btn-primary" type="submit" th:value="Hinzufügen"/>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h4>Mietgegenstand hinzufügen</h4>
|
||||
|
||||
<table class="table my-4">
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Preis/Stück (Pauschale)</th>
|
||||
<th>Preis/Stück/Stunde</th>
|
||||
<th>Verfügbar</th>
|
||||
<th>Menge</th>
|
||||
</tr>
|
||||
<tr th:each="item : ${invRentables.entrySet()}">
|
||||
<td th:text="${item.getKey().getName()}"></td>
|
||||
<td th:text="${item.getKey().getPrice()}"></td>
|
||||
<td th:text="${item.getKey().getPrice()}"></td>
|
||||
<td th:text="${item.getValue()}"></td>
|
||||
<td>
|
||||
<form th:action="@{/event/addProduct}" method="post">
|
||||
<input id="number" type="number" name="number" min="1" th:max="${item.getValue()}" value="1"/>
|
||||
<input type="hidden" name="pid" th:value="${item.getKey().getId()}"/>
|
||||
<input class="btn btn-primary" type="submit" th:value="Hinzufügen"/>
|
||||
</form>
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h4>Angestellte hinzufügen</h4>
|
||||
<table class="table">
|
||||
<table class="table my-4">
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Typ</th>
|
||||
|
@ -117,10 +139,10 @@
|
|||
<td></td>
|
||||
</tr>
|
||||
<tr th:each="employee : ${allStaff}">
|
||||
<td th:text="${employee.getName()}">Name</td>
|
||||
<td th:text="${employee.getJob()}">Job</td>
|
||||
<td th:text="'12€/h'">12€</td> <!--TODO: get from employee-->
|
||||
<td style="color: green" th:text="Verfügbar">Verfügbar</td> <!--TODO: get from employee-->
|
||||
<td th:text="${employee.getName()}"></td>
|
||||
<td th:text="${employee.getJob()}"></td>
|
||||
<td th:text="${employee.getWage()}"></td>
|
||||
<td style="color: green" th:text="Verfügbar"></td>
|
||||
<td>
|
||||
<form th:action="@{/event/addEmployee}" method="post">
|
||||
<input type="hidden" name="sid" th:value="${employee.getId()}"/>
|
||||
|
@ -130,4 +152,5 @@
|
|||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -23,18 +23,19 @@
|
|||
<td th:text="${order.getUserAccountIdentifier()}"/>
|
||||
<td>
|
||||
<div>
|
||||
<a href="#productDetails" th:text="${order.getOrderType()}"/>
|
||||
<strong class="text-danger" th:text="${order.getOrderType().toHumanReadable()}"/>
|
||||
<ul th:each="orderLine : ${order.getOrderLines()}">
|
||||
<li>
|
||||
<b th:text="${orderLine.getProductName()}"/><br>
|
||||
<th:block th:text="'Menge: ' + ${orderLine.getQuantity()}"/><br>
|
||||
<th:block th:text="'Preis: ' + ${orderLine.getPrice().getNumber().doubleValue() + ' €'}"/>
|
||||
<th:block th:text="'Pauschale: ' + ${orderLine.getPrice().getNumber().doubleValue()} + '€'"/><br>
|
||||
<th:block th:text="'Mietkosten: ' + ${order.getChargeLines(orderLine).getTotal().getNumber()} + '€'"/>
|
||||
</li>
|
||||
</ul>
|
||||
<ul th:each="employee : ${order.getStaff()}">
|
||||
<li>
|
||||
<b th:text="${employee.getName()} + ', ' + ${employee.getJob()}"/><br>
|
||||
<th:block th:text="'Preis: 12€/h'"/>
|
||||
<th:block th:text="'Preis: ' + ${order.getDurationInHours() * employee.getWage()}"/>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
@ -51,13 +52,10 @@
|
|||
<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="€"/>
|
||||
</td>
|
||||
<td th:text="${order.getTotal().getNumber().doubleValue()} + '€'"/>
|
||||
<td sec:authorize="hasRole('ADMIN')" th:if="${order.getOrderStatus()} != ${cancelled}">
|
||||
<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()}"/>
|
||||
<input class="btn btn-danger" type="submit" value="remove" th:value="Stornieren"/>
|
||||
</form>
|
||||
</td>
|
||||
|
|
|
@ -142,7 +142,7 @@ public class OrderControllerIntegrationTests {
|
|||
void userPlansEvent() throws Exception {
|
||||
mvc.perform(get("/event"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(model().attributeExists("invItems"));
|
||||
.andExpect(model().attributeExists("invRentables"));
|
||||
|
||||
Product product = inventory.findAll().stream().findFirst().get().getProduct();
|
||||
|
||||
|
|
112
src/test/java/catering/order/OrderControllerUnitTests.java
Normal file
112
src/test/java/catering/order/OrderControllerUnitTests.java
Normal file
|
@ -0,0 +1,112 @@
|
|||
package catering.order;
|
||||
|
||||
import catering.catalog.Rentable;
|
||||
import org.junit.jupiter.api.*;
|
||||
import org.salespointframework.inventory.UniqueInventory;
|
||||
import org.salespointframework.inventory.UniqueInventoryItem;
|
||||
import org.salespointframework.order.OrderManagement;
|
||||
import org.salespointframework.quantity.Quantity;
|
||||
import org.salespointframework.useraccount.UserAccount;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
@SpringBootTest
|
||||
public class OrderControllerUnitTests {
|
||||
@Autowired
|
||||
UniqueInventory<UniqueInventoryItem> inventory;
|
||||
|
||||
@Autowired
|
||||
OrderManagement<CustomOrder> orderManagement;
|
||||
|
||||
@Autowired
|
||||
CustomOrderRepository customOrderRepository;
|
||||
|
||||
Rentable myProduct;
|
||||
|
||||
@BeforeEach
|
||||
void setup() {
|
||||
// because of FUUUUUUUN
|
||||
if (!orderManagement.findAll(Pageable.unpaged()).isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// #1
|
||||
CustomCart myCart = new CustomCart(
|
||||
OrderType.EVENT_CATERING,
|
||||
LocalDateTime.of(2023, 12, 11, 9, 0),
|
||||
LocalDateTime.of(2023, 12, 13, 22, 0)
|
||||
);
|
||||
|
||||
myProduct = (Rentable) inventory.findAll()
|
||||
.filter(item -> item.getProduct().getName().equals("Kerze Rot"))
|
||||
.stream().findFirst().get().getProduct();
|
||||
|
||||
myCart.addOrUpdateItem(myProduct, 3);
|
||||
CustomOrder myOrder = new CustomOrder(UserAccount.UserAccountIdentifier.of("12345"), myCart);
|
||||
myCart.addItemsTo(myOrder);
|
||||
orderManagement.payOrder(myOrder);
|
||||
orderManagement.completeOrder(myOrder);
|
||||
|
||||
// #2
|
||||
myCart = new CustomCart(
|
||||
OrderType.EVENT_CATERING,
|
||||
LocalDateTime.of(2023, 12, 13, 9, 0),
|
||||
LocalDateTime.of(2023, 12, 15, 22, 0)
|
||||
);
|
||||
|
||||
myCart.addOrUpdateItem(myProduct, 4);
|
||||
myOrder = new CustomOrder(UserAccount.UserAccountIdentifier.of("12345"), myCart);
|
||||
myCart.addItemsTo(myOrder);
|
||||
orderManagement.payOrder(myOrder);
|
||||
orderManagement.completeOrder(myOrder);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
@Order(1)
|
||||
void thisShouldNeverFail() {
|
||||
assertThat(orderManagement.findAll(Pageable.unpaged()).stream().count()).isEqualTo(2L);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(2)
|
||||
void correctSetup() {
|
||||
assertThat(orderManagement.findAll(Pageable.unpaged()).stream().count()).isEqualTo(2L);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(3)
|
||||
void ordersByInterval() {
|
||||
assertThat(customOrderRepository.findOrdersByInterval(
|
||||
LocalDateTime.of(2023, 12, 2, 0, 0),
|
||||
LocalDateTime.of(2024, 1, 1, 0, 0)
|
||||
).stream().toList()).hasSize(2);
|
||||
|
||||
assertThat(customOrderRepository.findOrdersByInterval(
|
||||
LocalDateTime.of(2023, 12, 11, 0, 0),
|
||||
LocalDateTime.of(2023, 12, 11, 23, 0)
|
||||
).stream().toList()).hasSize(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(4)
|
||||
@Disabled // because Spring does shit that I don't understand
|
||||
void freeAmountInInterval() {
|
||||
myProduct = (Rentable) inventory.findAll()
|
||||
.filter(item -> item.getProduct().getName().equals("Kerze Rot"))
|
||||
.stream().findFirst().get().getProduct();
|
||||
|
||||
assertThat(OrderController.findFreeAmountInInterval(
|
||||
myProduct,
|
||||
LocalDateTime.of(2023, 12, 11, 0, 0),
|
||||
LocalDateTime.of(2023, 12, 11, 23, 0),
|
||||
inventory,
|
||||
customOrderRepository)
|
||||
).isEqualTo(Quantity.of(7));
|
||||
}
|
||||
}
|
|
@ -51,7 +51,7 @@ public class OrderUnitTests {
|
|||
|
||||
// test if ChargeLine is correct
|
||||
assertThat(order.getChargeLines().stream().count()).isEqualTo(1);
|
||||
assertThat(order.getChargeLines().getTotal()).isEqualTo(Money.of(11*12, "EUR"));
|
||||
assertThat(order.getChargeLines().getTotal()).isEqualTo(Money.of(11*employee.getWage(), "EUR"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -70,17 +70,17 @@ public class OrderUnitTests {
|
|||
assertThat(order.getChargeLines().stream().count()).isEqualTo(1);
|
||||
|
||||
// test if costs are correct
|
||||
assertThat(order.getChargeLines().getTotal()).isEqualTo(Money.of(11*12, "EUR"));
|
||||
assertThat(order.getChargeLines().getTotal()).isEqualTo(Money.of(11*employee.getWage(), "EUR"));
|
||||
assertThat(order.getOrderLines().getTotal()).isEqualTo(Money.of(10.0*0.6, "EUR"));
|
||||
assertThat(order.getTotal()).isEqualTo(Money.of(11.0 * 12.0 + 10.0 * 0.6, "EUR"));
|
||||
assertThat(order.getTotal()).isEqualTo(Money.of(11.0 * employee.getWage() + 10.0 * 0.6, "EUR"));
|
||||
|
||||
// test for duplication
|
||||
order.addEmployee(employee);
|
||||
assertThat(order.getStaff()).hasSize(1);
|
||||
assertThat(order.getOrderLines().stream().count()).isEqualTo(1);
|
||||
assertThat(order.getChargeLines().stream().count()).isEqualTo(1);
|
||||
assertThat(order.getChargeLines().getTotal()).isEqualTo(Money.of(11*12, "EUR"));
|
||||
assertThat(order.getChargeLines().getTotal()).isEqualTo(Money.of(11*employee.getWage(), "EUR"));
|
||||
assertThat(order.getOrderLines().getTotal()).isEqualTo(Money.of(10.0*0.6, "EUR"));
|
||||
assertThat(order.getTotal()).isEqualTo(Money.of(11.0 * 12.0 + 10.0 * 0.6, "EUR"));
|
||||
assertThat(order.getTotal()).isEqualTo(Money.of(11.0 * employee.getWage() + 10.0 * 0.6, "EUR"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ import catering.order.CustomOrder;
|
|||
import catering.order.OrderType;
|
||||
import catering.users.User;
|
||||
import catering.users.UserManagement;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
|
||||
@SpringBootTest
|
||||
class StaffManagmentIntegratonTest {
|
||||
|
@ -79,6 +80,7 @@ class StaffManagmentIntegratonTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
@DirtiesContext
|
||||
void getAvailableEmployees() throws Exception {
|
||||
Set<Employee> availableService = staffManagement.getAvailableStaffByJob(JobType.SERVICE,
|
||||
LocalDateTime.of(2023, 10, 27, 16, 0), LocalDateTime.of(2023, 10, 27, 18, 0));
|
||||
|
|
Loading…
Reference in a new issue