diff --git a/prototype/gradlew b/prototype/gradlew old mode 100644 new mode 100755 diff --git a/prototype/scripts/addarticles.sql b/prototype/scripts/addarticles.sql index b60497d..e81c174 100644 --- a/prototype/scripts/addarticles.sql +++ b/prototype/scripts/addarticles.sql @@ -1,6 +1,15 @@ -INSERT INTO article_offers ("manufacturer", "article_number", "price_per_unit_net", "title", "vat_percent", "should_be_advertised") -VALUES ("McDonalds", "1", 4242, "McPizza", 7, 1); +/* +* add a supplier first +*/ +INSERT INTO article_offers ("manufacturer", "article_number", "price_per_unit_net", "title", "vat_percent", "should_be_advertised", "cheapest_supplier_id") +VALUES ("McDonalds", "1", 4242, "McPizza", 7, 1, 1); + + + +/* +* There is no need for the add article, you can add one form the UI on the offerd article page +*/ INSERT INTO articles ("related_id", "shop_price_per_unit_net_cent", "warehouse_units_per_slot", "should_reorder", "reorder_max_price", "title", "description", "image_id") VALUES (1, 19.99, 10, 1, 15, "Huge Hamburger", "This huge Hamburger is awesome!", NULL); diff --git a/prototype/scripts/addsupplier.sql b/prototype/scripts/addsupplier.sql new file mode 100644 index 0000000..a56f4ed --- /dev/null +++ b/prototype/scripts/addsupplier.sql @@ -0,0 +1,6 @@ + +INSERT INTO suppliers ("api_url", "name", "uuid") +VALUES ("https://api.com", "Conrad", "fdfdfg4gdfgdf4gfg"); + + + diff --git a/prototype/scripts/addsupplierorders.sql b/prototype/scripts/addsupplierorders.sql new file mode 100644 index 0000000..6c19af3 --- /dev/null +++ b/prototype/scripts/addsupplierorders.sql @@ -0,0 +1,3 @@ + +INSERT INTO supplier_orders ("created", "delivered", "number_of_units", "price_per_unit_net_cent", "total_price_net", "ordered_id", "supplier_id") +VALUES ('0', '0', '42', '42', '42', '1', '1'); diff --git a/prototype/src/main/java/org/hso/ecommerce/action/booking/CreateBookingAction.java b/prototype/src/main/java/org/hso/ecommerce/action/booking/CreateBookingAction.java index f01e6a3..edde2cb 100644 --- a/prototype/src/main/java/org/hso/ecommerce/action/booking/CreateBookingAction.java +++ b/prototype/src/main/java/org/hso/ecommerce/action/booking/CreateBookingAction.java @@ -10,6 +10,7 @@ public class CreateBookingAction { public CreateBookingAction(BookingAccountEntry source, BookingAccountEntry destination, BookingReason reason, int amountCent) { booking = new Booking(); + booking.created = new java.sql.Timestamp(System.currentTimeMillis()); booking.reason = reason; booking.amountCent = amountCent; diff --git a/prototype/src/main/java/org/hso/ecommerce/action/cronjob/UpdateOffersAction.java b/prototype/src/main/java/org/hso/ecommerce/action/cronjob/UpdateOffersAction.java index f095381..e21869e 100644 --- a/prototype/src/main/java/org/hso/ecommerce/action/cronjob/UpdateOffersAction.java +++ b/prototype/src/main/java/org/hso/ecommerce/action/cronjob/UpdateOffersAction.java @@ -30,9 +30,10 @@ public class UpdateOffersAction { public List finish() { HashMap availableOffers = mapOffers(); - // Reset all advertise-flags first. They are set again below. + // Reset all advertise-flags and supplier relations first. They are set again below. for (ArticleOffer offer : availableOffers.values()) { offer.shouldBeAdvertised = false; + offer.cheapestSupplier = null; } for (Entry cheapestOffer : cheapestOffer.entrySet()) { @@ -47,7 +48,10 @@ public class UpdateOffersAction { } Article currentOfferedArticle = cheapestOffer.getValue().apiSupplier.findArticle(manufacturer, articleNumber); + currentOffer.title = currentOfferedArticle.title; currentOffer.vatPercent = currentOfferedArticle.vatPercent; + currentOffer.cheapestSupplier = cheapestOffer.getValue().dbSupplier; + currentOffer.pricePerUnitNet = currentOfferedArticle.pricePerUnitNet; // Set advertise-flag if any supplier wants it to be set if (currentOfferedArticle.shouldBeAdvertised) { diff --git a/prototype/src/main/java/org/hso/ecommerce/action/shop/CreateOrderAction.java b/prototype/src/main/java/org/hso/ecommerce/action/shop/CreateOrderAction.java index 8b35be8..854be3a 100644 --- a/prototype/src/main/java/org/hso/ecommerce/action/shop/CreateOrderAction.java +++ b/prototype/src/main/java/org/hso/ecommerce/action/shop/CreateOrderAction.java @@ -74,9 +74,15 @@ public class CreateOrderAction { CustomerPayment payment = createPayment(); List bookingList = new ArrayList<>(); - bookingList.add(new CreateBookingAction(latestUserBooking, latestMainBooking, new BookingReason(order), order.totalGrossCent).finish()); - bookingList.add(new CreateBookingAction(null, latestUserBooking, new BookingReason(payment), order.totalGrossCent).finish()); - bookingList.add(new CreateBookingAction(latestMainBooking, latestVatBooking, new BookingReason(order), order.totalVatCent).finish()); + Booking purchaseBooking = new CreateBookingAction( + latestUserBooking, latestMainBooking, new BookingReason(order), order.totalGrossCent).finish(); + Booking paymentBooking = new CreateBookingAction( + null, purchaseBooking.source /* userAccount */, new BookingReason(payment), order.totalGrossCent).finish(); + Booking vatBooking = new CreateBookingAction( + purchaseBooking.destination /* mainAccount */, latestVatBooking, new BookingReason(order), order.totalVatCent).finish(); + bookingList.add(purchaseBooking); + bookingList.add(paymentBooking); + bookingList.add(vatBooking); WarehouseBooking warehouseBooking = createWarehouseBooking(order); @@ -103,7 +109,7 @@ public class CreateOrderAction { bookingPosition.article = item.article; bookingPosition.amount = -remove; - bookingPosition.slotEntry = slot.copyAddAmount(-remove); + bookingPosition.slotEntry = slot.copyAddAmount(-remove, item.article); bookingPosition.booking = booking; booking.positions.add(bookingPosition); diff --git a/prototype/src/main/java/org/hso/ecommerce/action/shop/SearchByTermAction.java b/prototype/src/main/java/org/hso/ecommerce/action/shop/SearchByTermAction.java new file mode 100644 index 0000000..cfdfffe --- /dev/null +++ b/prototype/src/main/java/org/hso/ecommerce/action/shop/SearchByTermAction.java @@ -0,0 +1,40 @@ +package org.hso.ecommerce.action.shop; + +import org.hso.ecommerce.entities.shop.Article; +import org.hso.ecommerce.repos.shop.ArticleRepository; +import org.springframework.beans.factory.annotation.Autowired; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class SearchByTermAction { + + public static List
searchByTerm(String sourceTerm, ArticleRepository repository) { + + List terms = Arrays.asList(sourceTerm.split(" ")); + List
resultArticles = new ArrayList<>(); + + terms.forEach(term -> { + List
titleArticles = repository.getArticlesByTermInTitle(term); //search in Title + titleArticles.forEach(article -> { + if(!resultArticles.contains(article)){ + resultArticles.add(article); + } + }); + + }); + + terms.forEach(term -> { + List
descArticles = repository.getArticlesByTermInDescription(term); //search by Term + descArticles.forEach(article -> { + if(!resultArticles.contains(article)){ + resultArticles.add(article); + } + }); + + }); + + return resultArticles; + } +} diff --git a/prototype/src/main/java/org/hso/ecommerce/action/user/UpdateUserSettingsAction.java b/prototype/src/main/java/org/hso/ecommerce/action/user/UpdateUserSettingsAction.java new file mode 100644 index 0000000..ba17181 --- /dev/null +++ b/prototype/src/main/java/org/hso/ecommerce/action/user/UpdateUserSettingsAction.java @@ -0,0 +1,83 @@ +package org.hso.ecommerce.action.user; + +import org.hso.ecommerce.entities.booking.PaymentMethod; +import org.hso.ecommerce.entities.user.User; +import org.hso.ecommerce.repos.user.UserRepository; + +public class UpdateUserSettingsAction { + + private User user; + private UserRepository repository; + + public UpdateUserSettingsAction(User user, UserRepository repository) { + this.user = user; + this.repository = repository; + } + + public UpdateResult updateEmail(String newMail) { + UpdateResult result = new UpdateResult(false); + if (!newMail.contains("@")) { + result.errorString = "Ändern der Email-Addresse nicht möglich. Bitte versuchen Sie es erneut."; + } else { + this.user.email = newMail; + this.repository.save(this.user); + result.updated = true; + } + return result; + } + + public UpdateResult updatePassword(String oldPassword, String password1, String password2) { + UpdateResult result = new UpdateResult(false); + if (this.user.validatePassword(oldPassword)) { + if (password1.equals(password2)) { + if (!password1.equals(oldPassword)) { + this.user.setPassword(password1); + this.repository.save(this.user); + result.updated = true; + } else { + result.errorString = "Das neue Passwort entspricht dem alten Passwort."; + } + } else { + result.errorString = "Die beiden neuen Passwörter stimmen nicht überein. Bitte versuchen Sie es erneut."; + } + } else { + result.errorString = "Das eingegebene alte Passwort stimmt nicht mit dem momentan gespeicherten Passwort überein. Bitte versuchen Sie es erneut."; + } + return result; + } + + public UpdateResult updateShippingInfo(String salutation, String name, String address) { + this.user.salutation = salutation; + this.user.name = name; + this.user.defaultDeliveryAddress.addressString = address; + this.repository.save(this.user); + return new UpdateResult(true); + } + + public UpdateResult updatePaymentInfo(String creditCardNumber) { + UpdateResult result = new UpdateResult(false); + if (creditCardNumber.matches("[0-9]+")) { + this.user.defaultPayment = PaymentMethod.fromCreditCardNumber(creditCardNumber); + this.repository.save(this.user); + result.updated = true; + } else { + result.errorString = "Kreditkartennummer darf nur Zahlen enthalten. Bitte versuchen Sie es erneut."; + } + return result; + } + + public class UpdateResult { + public boolean updated; //if true worked, if false not worked + public String errorString; + + public UpdateResult(boolean updated, String errorString) { + this.updated = updated; + this.errorString = errorString; + } + + public UpdateResult(boolean updated) { + this.updated = updated; + this.errorString = ""; + } + } +} diff --git a/prototype/src/main/java/org/hso/ecommerce/action/warehouse/CalculateWarehouseStatsAction.java b/prototype/src/main/java/org/hso/ecommerce/action/warehouse/CalculateWarehouseStatsAction.java new file mode 100644 index 0000000..ca5c5dc --- /dev/null +++ b/prototype/src/main/java/org/hso/ecommerce/action/warehouse/CalculateWarehouseStatsAction.java @@ -0,0 +1,73 @@ +package org.hso.ecommerce.action.warehouse; + +import org.hso.ecommerce.entities.warehouse.WarehouseBookingPositionSlotEntry; + +import java.util.HashSet; +import java.util.List; + +public class CalculateWarehouseStatsAction { + + private List entryList; + + public CalculateWarehouseStatsAction(List everyCurrentEntry) { + this.entryList = everyCurrentEntry; + } + + public WarehouseStats finish() { + int numArticles = calculateNumArticles(); + double efficiency = calculateEfficiency(); + double ratioUsedSlots = calculateRatioSlotsUsed(); + + return new WarehouseStats(numArticles, efficiency, ratioUsedSlots); + } + + private double calculateRatioSlotsUsed() { + int used = 0; + + for (WarehouseBookingPositionSlotEntry entry : entryList) { + if (entry.newSumSlot > 0) { + used++; + } + } + + return ((double) used) / entryList.size(); + } + + private double calculateEfficiency() { + double e = 0; + + for (WarehouseBookingPositionSlotEntry entry : entryList) { + if (entry.newSumSlot > 0) { + e += entry.newSumSlot / (double) entry.article.warehouseUnitsPerSlot; + } else { + e += 0; + } + } + + return e / entryList.size(); + } + + private int calculateNumArticles() { + HashSet articleIds = new HashSet<>(); + + for (WarehouseBookingPositionSlotEntry entry : entryList) { + if (entry.newSumSlot > 0) { + articleIds.add(entry.article.id); + } + } + + return articleIds.size(); + } + + private static class WarehouseStats { + public int numArticles; + public double efficiency; + public double ratioUsedSlots; + + WarehouseStats(int numArticles, double efficiency, double ratioUsedSlots) { + this.numArticles = numArticles; + this.efficiency = efficiency; + this.ratioUsedSlots = ratioUsedSlots; + } + } +} diff --git a/prototype/src/main/java/org/hso/ecommerce/action/warehouse/CreateManuelBookingAction.java b/prototype/src/main/java/org/hso/ecommerce/action/warehouse/CreateManuelBookingAction.java new file mode 100644 index 0000000..0a148b2 --- /dev/null +++ b/prototype/src/main/java/org/hso/ecommerce/action/warehouse/CreateManuelBookingAction.java @@ -0,0 +1,92 @@ +package org.hso.ecommerce.action.warehouse; + +import org.hso.ecommerce.entities.booking.BookingReason; +import org.hso.ecommerce.entities.shop.Article; +import org.hso.ecommerce.entities.warehouse.WarehouseBooking; +import org.hso.ecommerce.entities.warehouse.WarehouseBookingPosition; +import org.hso.ecommerce.entities.warehouse.WarehouseBookingPositionSlotEntry; + +import java.sql.Timestamp; +import java.util.Date; +import java.util.Optional; + +public class CreateManuelBookingAction { + + private Article article; + private int amount; + private Optional source; + private Optional destination; + private String reason; + + public CreateManuelBookingAction(Article article, int amount, Optional source, Optional destination, String reason) { + this.article = article; + this.amount = amount; + this.source = source; + this.destination = destination; + this.reason = reason; + } + + public WarehouseBooking finish() throws ArticleSlotConstraintFailedException { + WarehouseBooking booking = new WarehouseBooking(); + booking.created = new Timestamp(new Date().getTime()); + booking.reason = new BookingReason(reason); + + if (source.isPresent()) { + + if (source.get().article.id != article.id) { + throw new ArticleSlotConstraintArticleTypeFailedException(); + } + + WarehouseBookingPosition bookingPosition = new WarehouseBookingPosition(); + bookingPosition.booking = booking; + + bookingPosition.article = article; + bookingPosition.amount = -amount; + bookingPosition.slotEntry = source.get().copyAddAmount(-amount, article); + + if (bookingPosition.slotEntry.newSumSlot < 0 || bookingPosition.slotEntry.newSumSlot > article.warehouseUnitsPerSlot) { + throw new ArticleSlotConstraintFailedException("The quantity of article can only be set in bounds."); + } + + booking.positions.add(bookingPosition); + } + + if (destination.isPresent()) { + + if (destination.get().article.id != article.id && destination.get().newSumSlot > 0) { + throw new ArticleSlotConstraintArticleTypeFailedException(); + } + + WarehouseBookingPosition bookingPosition = new WarehouseBookingPosition(); + bookingPosition.booking = booking; + + bookingPosition.article = article; + bookingPosition.amount = amount; + bookingPosition.slotEntry = destination.get().copyAddAmount(amount, article); + + if (bookingPosition.slotEntry.newSumSlot < 0 || bookingPosition.slotEntry.newSumSlot > article.warehouseUnitsPerSlot) { + throw new ArticleSlotConstraintFailedException("The quantity of article can only be set in bounds."); + } + + booking.positions.add(bookingPosition); + } + + return booking; + } + + public static class ArticleSlotConstraintFailedException extends Exception { + public ArticleSlotConstraintFailedException(String s) { + super(s); + } + + public ArticleSlotConstraintFailedException() { + super("The quantity of article can only be set in bounds."); + } + } + + public static class ArticleSlotConstraintArticleTypeFailedException extends ArticleSlotConstraintFailedException { + public ArticleSlotConstraintArticleTypeFailedException() { + super("The Article in the slot entry does not match."); + } + } +} diff --git a/prototype/src/main/java/org/hso/ecommerce/action/warehouse/SupplierOrderArrivedAction.java b/prototype/src/main/java/org/hso/ecommerce/action/warehouse/SupplierOrderArrivedAction.java new file mode 100644 index 0000000..dc361b0 --- /dev/null +++ b/prototype/src/main/java/org/hso/ecommerce/action/warehouse/SupplierOrderArrivedAction.java @@ -0,0 +1,103 @@ +package org.hso.ecommerce.action.warehouse; + +import org.hso.ecommerce.entities.booking.BookingReason; +import org.hso.ecommerce.entities.shop.Article; +import org.hso.ecommerce.entities.supplier.SupplierOrder; +import org.hso.ecommerce.entities.warehouse.WarehouseBooking; +import org.hso.ecommerce.entities.warehouse.WarehouseBookingPosition; +import org.hso.ecommerce.entities.warehouse.WarehouseBookingPositionSlotEntry; + +import java.sql.Timestamp; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +public class SupplierOrderArrivedAction { + + private final Article article; + private final ArrayList warehouseCandidates; + private final SupplierOrder order; + + public SupplierOrderArrivedAction(List warehouseCandidates, SupplierOrder order, Article article) { + this.warehouseCandidates = new ArrayList<>(warehouseCandidates); + this.order = order; + this.article = article; + } + + public Result finish() throws NoSpaceInWarehouseException { + // Sort for most filled slot first; + warehouseCandidates.sort((b, a) -> Integer.compare(a.newSumSlot, b.newSumSlot)); + + int needed = order.numberOfUnits; + + WarehouseBooking booking = new WarehouseBooking(); + booking.created = new Timestamp(new Date().getTime()); + booking.reason = new BookingReason(order); + + for (WarehouseBookingPositionSlotEntry entry : warehouseCandidates) { + int canBeAdded = article.warehouseUnitsPerSlot - entry.newSumSlot; + + if (canBeAdded == 0) { + // this slot is full, skip + continue; + } + + int willBeAdded = Math.min(canBeAdded, needed); + needed -= willBeAdded; + + WarehouseBookingPosition bookingPosition = new WarehouseBookingPosition(); + + bookingPosition.article = article; + bookingPosition.amount = willBeAdded; + bookingPosition.slotEntry = entry.copyAddAmount(willBeAdded, article); + bookingPosition.booking = booking; + + booking.positions.add(bookingPosition); + + if (needed == 0) { + break; + } + } + + if (needed > 0) { + throw new NoSpaceInWarehouseException(article); + } + + order.delivered = new Timestamp(new Date().getTime()); + return new Result(order, booking); + } + + public static class Result extends Exception { + + private final SupplierOrder order; + private final WarehouseBooking booking; + + public Result(SupplierOrder order, WarehouseBooking booking) { + this.order = order; + this.booking = booking; + } + + public SupplierOrder getOrder() { + return order; + } + + public WarehouseBooking getBooking() { + return booking; + } + } + + + public static class NoSpaceInWarehouseException extends Exception { + private Article article; + + public NoSpaceInWarehouseException(Article article) { + super("The quantity of article '" + article.title + "' does not fit in warehouse."); + this.article = article; + } + + public Article getArticle() { + return article; + } + } + +} diff --git a/prototype/src/main/java/org/hso/ecommerce/app/RequestController.java b/prototype/src/main/java/org/hso/ecommerce/app/RequestController.java deleted file mode 100644 index 17b351e..0000000 --- a/prototype/src/main/java/org/hso/ecommerce/app/RequestController.java +++ /dev/null @@ -1,176 +0,0 @@ -package org.hso.ecommerce.app; - -import org.hso.ecommerce.entities.user.User; -import org.hso.ecommerce.repos.user.UserRepository; -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; -import org.springframework.web.bind.annotation.RequestParam; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpSession; -import java.util.Optional; - -/** - * TODO clean up this class - */ -@Controller -public class RequestController { - - @Autowired - private final UserRepository userRepository = null; - - static int notSoRandom = 0; - - @GetMapping("/login") - public String login() { - return "login"; - } - - @PostMapping("/login") - public String loginPost( - HttpServletRequest request, - HttpServletResponse response, - @RequestParam("username") String username, - @RequestParam("password") String password, - HttpSession session - ) { - String gto = (String) session.getAttribute("afterLogin"); - - Optional user = userRepository.findByEmail(username); - if (!user.isPresent()) { - request.setAttribute("error", "Email Adresse falsch."); - response.setStatus(HttpServletResponse.SC_EXPECTATION_FAILED); - return "login"; - } - - if (!user.get().validatePassword(password)) { - request.setAttribute("error", "Passwort falsch."); - response.setStatus(HttpServletResponse.SC_EXPECTATION_FAILED); - return "login"; - } - - if (!user.get().isActive) { - request.setAttribute("error", "User ist deaktiviert."); - response.setStatus(HttpServletResponse.SC_EXPECTATION_FAILED); - return "login"; - } - - session.setAttribute("userId", user.get().getId()); - - if (gto != null && gto.startsWith("/")) { - return "redirect:" + gto; - } else { - return "redirect:/"; - } - } - - @PostMapping("/logout") - public String logoutPost(HttpServletResponse response, - HttpSession session - ) { - session.removeAttribute("userId"); - return "redirect:/"; - } - - @GetMapping("/intern/") - public String intern() { - return "intern/index"; - } - - @GetMapping("/intern/customers/") - public String internCustomers() { - return "intern/customers/index"; - } - - @GetMapping("/intern/customers/{id}") - public String internCustomersId() { - return "intern/customers/id"; - } - - @GetMapping("/intern/suppliers/") - public String internSuppliers() { - return "intern/suppliers/index"; - } - - @GetMapping("/intern/suppliers/{id}") - public String internSuppliersId() { - return "intern/suppliers/id"; - } - - @GetMapping("/intern/supplierOrders/") - public String internSupplierOrders() { - return "intern/supplierOrders/index"; - } - - @GetMapping("/intern/supplierOrders/{id}") - public String internSupplierOrdersId() { - return "intern/supplierOrders/id"; - } - - /* - - @GetMapping("/intern/suppliersOffers") - public String internSuppliersOffers() { - return "intern/offeredArticles/index"; - } - */ - - - @GetMapping("/intern/accounting/") - public String accounting() { - return "intern/accounting/index"; - } - - @GetMapping("/intern/accounting/vat") - public String accountingVat() { - return "intern/accounting/vat"; - } - - @GetMapping("/intern/accounting/main") - public String accountingIntern() { - return "intern/accounting/main"; - } - - @GetMapping("/intern/accounting/addManual") - public String accountingAddManual() { - return "intern/accounting/addManual"; - } - - @GetMapping("/intern/warehouse/") - public String accountingWarehouse() { - return "intern/warehouse/index"; - } - - @GetMapping("/intern/warehouse/todo") - public String accountingWarehouseTodo() { - return "intern/warehouse/todo"; - } - - @GetMapping("/intern/warehouse/addManual") - public String accountingWarehouseAddManual() { - return "intern/warehouse/addManual"; - } - - @PostMapping("/intern/warehouse/progress/{id}") - public String accountingWarehouseProgressIdPost(HttpServletResponse response) { - if ((notSoRandom++) % 2 == 1) { - return "redirect:/intern/warehouse/progress/450"; - } else { - response.setStatus(409); - return "intern/warehouse/error_progress_failed"; - } - } - - @GetMapping("/intern/warehouse/progress/{id}") - public String accountingWarehouseProgressId() { - return "intern/warehouse/id_progress"; - } - - @GetMapping("/intern/warehouse/slots/") - public String accountingWarehouseSlots() { - return "intern/warehouse/slots/index"; - } -} diff --git a/prototype/src/main/java/org/hso/ecommerce/app/UserRequestController.java b/prototype/src/main/java/org/hso/ecommerce/app/UserRequestController.java deleted file mode 100644 index c4f6301..0000000 --- a/prototype/src/main/java/org/hso/ecommerce/app/UserRequestController.java +++ /dev/null @@ -1,36 +0,0 @@ -package org.hso.ecommerce.app; - -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; - -@Controller -@RequestMapping("user") -public class UserRequestController { - - @GetMapping("/") - public String user() { - return "redirect:/user/settings"; - } - - @GetMapping("/settings") - public String userSettings() { - return "user/settings"; - } - - @GetMapping("/orders/") - public String userOrdeers() { - return "user/orders/index"; - } - - @GetMapping("/bonuspoints") - public String userBonuspoints() { - return "user/bonuspoints"; - } - - @GetMapping("/notifications/") - public String userNotifications() { - return "user/notifications/index"; - } -} - diff --git a/prototype/src/main/java/org/hso/ecommerce/controller/BookingController.java b/prototype/src/main/java/org/hso/ecommerce/controller/BookingController.java deleted file mode 100644 index d35093e..0000000 --- a/prototype/src/main/java/org/hso/ecommerce/controller/BookingController.java +++ /dev/null @@ -1,8 +0,0 @@ -package org.hso.ecommerce.controller; - -import org.springframework.stereotype.Controller; - -@Controller -//@RequestMapping("...") -public class BookingController { -} diff --git a/prototype/src/main/java/org/hso/ecommerce/controller/LoginController.java b/prototype/src/main/java/org/hso/ecommerce/controller/LoginController.java index 5f4ebad..94182ce 100644 --- a/prototype/src/main/java/org/hso/ecommerce/controller/LoginController.java +++ b/prototype/src/main/java/org/hso/ecommerce/controller/LoginController.java @@ -1,8 +1,69 @@ package org.hso.ecommerce.controller; +import java.util.Optional; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +import org.hso.ecommerce.entities.user.User; +import org.hso.ecommerce.repos.user.UserRepository; +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; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; @Controller -//@RequestMapping("...") +@RequestMapping("/") public class LoginController { + + @Autowired + private final UserRepository userRepository = null; + + @GetMapping("login") + public String login() { + return "login"; + } + + @PostMapping("login") + public String loginPost(HttpServletRequest request, HttpServletResponse response, + @RequestParam("username") String username, @RequestParam("password") String password, HttpSession session) { + + String gto = (String) session.getAttribute("afterLogin"); + + Optional user = userRepository.findByEmail(username); + if (!user.isPresent()) { + request.setAttribute("error", "Die Email Adresse falsch."); + response.setStatus(HttpServletResponse.SC_EXPECTATION_FAILED); + return "login"; + } + + if (!user.get().validatePassword(password)) { + request.setAttribute("error", "Das Passwort ist falsch."); + response.setStatus(HttpServletResponse.SC_EXPECTATION_FAILED); + return "login"; + } + + if (!user.get().isActive) { + request.setAttribute("error", "Dieses Konto ist deaktiviert.."); + response.setStatus(HttpServletResponse.SC_EXPECTATION_FAILED); + return "login"; + } + + session.setAttribute("userId", user.get().getId()); + + if (gto != null && gto.startsWith("/")) { + return "redirect:" + gto; + } else { + return "redirect:/"; + } + } + + @PostMapping("logout") + public String logoutPost(HttpServletResponse response, HttpSession session) { + session.removeAttribute("userId"); + return "redirect:/"; + } } diff --git a/prototype/src/main/java/org/hso/ecommerce/controller/RegisterController.java b/prototype/src/main/java/org/hso/ecommerce/controller/RegisterController.java index a53e084..36fcdef 100644 --- a/prototype/src/main/java/org/hso/ecommerce/controller/RegisterController.java +++ b/prototype/src/main/java/org/hso/ecommerce/controller/RegisterController.java @@ -1,5 +1,6 @@ package org.hso.ecommerce.controller; +import org.hso.ecommerce.entities.booking.PaymentMethod; import org.hso.ecommerce.entities.shop.Address; import org.hso.ecommerce.entities.user.User; import org.hso.ecommerce.repos.user.UserRepository; @@ -11,64 +12,71 @@ import org.springframework.web.bind.annotation.RequestParam; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; import java.util.Optional; @Controller -public class RegisterController { +public class RegisterController { - @Autowired - private final UserRepository userRepository = null; + @Autowired + private final UserRepository userRepository = null; - @PostMapping("/register") - public String registerPost( - HttpServletRequest request, - HttpServletResponse response, - @RequestParam("username") String username, - @RequestParam("password") String password, - @RequestParam("password2") String password2, - @RequestParam("salutation") String salutation, - @RequestParam("name") String name, - @RequestParam("address") String address, - @RequestParam("type") String type, - @RequestParam("ad") String ad - ) - { - Optional user = userRepository.findByEmail(username); - if (user.isPresent()) { - request.setAttribute("error", "Email Adresse existiert bereits!"); - response.setStatus(HttpServletResponse.SC_EXPECTATION_FAILED); - return "register"; - } + @PostMapping("/register") + public String registerPost(HttpServletRequest request, HttpServletResponse response, + @RequestParam("username") String username, @RequestParam("password") String password, + @RequestParam("password2") String password2, @RequestParam("salutation") String salutation, + @RequestParam("name") String name, @RequestParam("address") String address, + @RequestParam("type") String type, // TODO store + @RequestParam("ad") String ad, // TODO store + HttpSession session) { + Optional user = userRepository.findByEmail(username); + if (user.isPresent()) { + request.setAttribute("error", "Die Email Adresse existiert bereits."); + response.setStatus(HttpServletResponse.SC_EXPECTATION_FAILED); + return "register"; + } - if (!password.equals(password2)){ - request.setAttribute("error", "Passwörter sind nicht gleich"); - response.setStatus(HttpServletResponse.SC_BAD_REQUEST); - return "register"; - } + if (!password.equals(password2)) { + request.setAttribute("error", "Die Passwörter stimmen nicht überein."); + response.setStatus(HttpServletResponse.SC_BAD_REQUEST); + return "register"; + } - //set values for new user - User newUser = new User(); - newUser.email = username; - newUser.setPassword(password); - newUser.email = username; - newUser.isEmployee = false; - //TODO for salutation, type, ad are no attributes/fields in the class/database. Add when they are there. + // set values for new user + User newUser = new User(); + newUser.email = username; + newUser.setPassword(password); + newUser.email = username; + newUser.isEmployee = false; + newUser.salutation = salutation; + newUser.defaultPayment = PaymentMethod.fromCreditCardNumber(""); - newUser.isActive = true; - newUser.created = new java.sql.Timestamp(System.currentTimeMillis()); + newUser.isActive = true; + newUser.created = new java.sql.Timestamp(System.currentTimeMillis()); - Address newAddress = new Address(); - newAddress.name = name; - newAddress.addressString = address; - newUser.defaultDeliveryAddress = newAddress; + Address newAddress = new Address(); + newAddress.name = name; + newAddress.addressString = address; + newUser.defaultDeliveryAddress = newAddress; - userRepository.save(newUser); // save newUser + userRepository.save(newUser); // save newUser - return "redirect:/login"; - } + user = userRepository.findByEmail(username); + session.setAttribute("userId", user.get().getId()); - @GetMapping("/register") - public String register() { - return "register"; - } + String gto = (String) session.getAttribute("afterLogin"); + + //login after register + if (gto != null && gto.startsWith("/")) { + return "redirect:" + gto; + } else { + return "redirect:/"; + } + + } + + @GetMapping("/register") + public String register() { + return "register"; + } } diff --git a/prototype/src/main/java/org/hso/ecommerce/controller/UserController.java b/prototype/src/main/java/org/hso/ecommerce/controller/UserController.java index 523bf2e..8a90d43 100644 --- a/prototype/src/main/java/org/hso/ecommerce/controller/UserController.java +++ b/prototype/src/main/java/org/hso/ecommerce/controller/UserController.java @@ -1,8 +1,127 @@ package org.hso.ecommerce.controller; +import org.hso.ecommerce.action.user.UpdateUserSettingsAction; +import org.hso.ecommerce.entities.shop.CustomerOrder; +import org.hso.ecommerce.entities.user.User; +import org.hso.ecommerce.repos.shop.CustomerOrderRepository; +import org.hso.ecommerce.repos.user.UserRepository; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; +import java.util.List; @Controller -//@RequestMapping("...") +@RequestMapping("/user") public class UserController { + + @Autowired + private final UserRepository userRepository = null; + + @Autowired + private final CustomerOrderRepository customerOrderRepository = null; + + @GetMapping("/") + public String user() { + return "redirect:/user/settings"; + } + + @GetMapping("/settings") + public String userSettings(Model model, + HttpSession session + ) { + long userId = (long) session.getAttribute("userId"); + User user = userRepository.findById(userId).get(); + model.addAttribute("user", user); + + return "user/settings"; + } + + @GetMapping("/orders/") + public String userOrdeers(HttpSession session, + Model model + ) { + List orders = customerOrderRepository.getOrdersByUserId((long) session.getAttribute("userId")); + model.addAttribute("orders", orders); + + return "user/orders/index"; + } + + @PostMapping("/settings/changeMail") + public String changeMail(HttpSession session, + @RequestParam("email") String email, + HttpServletRequest request + ) { + User user = userRepository.findById((long) session.getAttribute("userId")).get(); + + UpdateUserSettingsAction cusa = new UpdateUserSettingsAction(user, userRepository); + UpdateUserSettingsAction.UpdateResult result = cusa.updateEmail(email); + if (result.updated == false) { + request.setAttribute("error", result.errorString); + return "user/settings"; + } + + return "redirect:/user/settings"; + } + + @PostMapping("/settings/changePwd") + public String changePwd(HttpSession session, + @RequestParam("old-password") String oldPassword, + @RequestParam("password1") String password1, + @RequestParam("password2") String password2, + HttpServletRequest request + ) { + User user = userRepository.findById((long) session.getAttribute("userId")).get(); + + UpdateUserSettingsAction cusa = new UpdateUserSettingsAction(user, userRepository); + UpdateUserSettingsAction.UpdateResult result = cusa.updatePassword(oldPassword, password1, password2); + if (result.updated == false) { + request.setAttribute("error", result.errorString); + return "user/settings"; + } + + return "redirect:/user/settings"; + } + + @PostMapping("/settings/changeAddress") + public String changeAddress(HttpSession session, + @RequestParam("salutation") String salutation, + @RequestParam("name") String name, + @RequestParam("address") String address, + HttpServletRequest request + ) { + User user = userRepository.findById((long) session.getAttribute("userId")).get(); + + UpdateUserSettingsAction cusa = new UpdateUserSettingsAction(user, userRepository); + UpdateUserSettingsAction.UpdateResult result = cusa.updateShippingInfo(salutation, name, address); + if (result.updated == false) { + request.setAttribute("error", result.errorString); + return "user/settings"; + } + + return "redirect:/user/settings"; + } + + @PostMapping("/settings/changePaymentInfo") + public String changePaymentInfo(HttpSession session, + @RequestParam("creditCardNumber") String creditCardNumber, + HttpServletRequest request + ) { + User user = userRepository.findById((long) session.getAttribute("userId")).get(); + + UpdateUserSettingsAction cusa = new UpdateUserSettingsAction(user, userRepository); + UpdateUserSettingsAction.UpdateResult result = cusa.updatePaymentInfo(creditCardNumber); + if (result.updated == false) { + request.setAttribute("error", result.errorString); + return "user/settings"; + } + + return "redirect:/user/settings"; + } } diff --git a/prototype/src/main/java/org/hso/ecommerce/controller/cronjob/CronjobController.java b/prototype/src/main/java/org/hso/ecommerce/controller/cronjob/CronjobController.java index e2bad65..0f54221 100644 --- a/prototype/src/main/java/org/hso/ecommerce/controller/cronjob/CronjobController.java +++ b/prototype/src/main/java/org/hso/ecommerce/controller/cronjob/CronjobController.java @@ -28,7 +28,7 @@ import org.hso.ecommerce.repos.booking.BookingAccountEntryRepository; import org.hso.ecommerce.repos.booking.BookingRepository; import org.hso.ecommerce.repos.cronjob.BackgroundJobRepository; import org.hso.ecommerce.repos.shop.ArticleRepository; -import org.hso.ecommerce.repos.shop.CustomerOderRepository; +import org.hso.ecommerce.repos.shop.CustomerOrderRepository; import org.hso.ecommerce.repos.supplier.ArticleOfferRepository; import org.hso.ecommerce.repos.supplier.SupplierOrderRepository; import org.hso.ecommerce.repos.supplier.SupplierRepository; @@ -230,7 +230,7 @@ class CronjobController { final ArticleOfferRepository articleOfferRepository = null; @Autowired - final CustomerOderRepository customerOrderRepository = null; + final CustomerOrderRepository customerOrderRepository = null; @Autowired final BookingRepository bookingRepository = null; diff --git a/prototype/src/main/java/org/hso/ecommerce/controller/intern/InternArticleController.java b/prototype/src/main/java/org/hso/ecommerce/controller/intern/InternArticleController.java index 35d76f8..e799210 100644 --- a/prototype/src/main/java/org/hso/ecommerce/controller/intern/InternArticleController.java +++ b/prototype/src/main/java/org/hso/ecommerce/controller/intern/InternArticleController.java @@ -1,15 +1,5 @@ package org.hso.ecommerce.controller.intern; -import java.awt.image.BufferedImage; -import java.io.File; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import javax.imageio.ImageIO; - import org.hso.ecommerce.entities.shop.Article; import org.hso.ecommerce.entities.shop.Category; import org.hso.ecommerce.entities.shop.Image; @@ -27,6 +17,16 @@ import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import org.springframework.web.servlet.view.RedirectView; +import javax.imageio.ImageIO; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + @Controller @RequestMapping("intern/articles") public class InternArticleController { @@ -62,16 +62,12 @@ public class InternArticleController { @GetMapping("/{id}") public String internListedArticlesId(Model model, @PathVariable String id) { - int articleid = Integer.parseInt(id); - UImodelArticle total = new UImodelArticle(); - total.addArticle(articleRepository.findArticleById(articleid), warehouseEntryRepository.getArticleStock(articleid).orElse(0)); model.addAttribute("ArticleID", total); - return "intern/listedArticles/id"; } @@ -80,7 +76,7 @@ public class InternArticleController { @RequestParam(value = "title", required = true) String title, @RequestParam(value = "description", required = true) String description, @RequestParam(value = "units-per-slot", required = true) String warehouseUnitsPerSlot, - @RequestParam(value = "price_netto", required = true) String pricenetto, + @RequestParam(value = "priceNet", required = true) String pricenetto, @RequestParam(value = "reorderMaxPrice", required = true) String reorderMaxPrice, @RequestParam(value = "autobuy", required = true) Boolean shouldReorder, @RequestParam(value = "categorie", required = true) String categories, @@ -148,9 +144,9 @@ public class InternArticleController { File tmpFile = new File(defaultImagePath); // test if default img file exits if (!tmpFile.exists()) { - // fallback if the file not exists + // fallback if the file not exists // create new file - BufferedImage bufferedImage = new BufferedImage(422, 428, BufferedImage.TYPE_INT_RGB); + BufferedImage bufferedImage = new BufferedImage(422, 428, BufferedImage.TYPE_INT_RGB); try { ImageIO.write(bufferedImage, "jpg", new File(defaultImagePath)); // save new file on disk } catch (IOException e) { @@ -192,25 +188,21 @@ public class InternArticleController { public static class UImodelArticles { public String imgPath; - public String title; - public String price; - - public String price_netto; - + public String priceNet; public String categorie; - public int stock; - - public long offer_id; - + public long offerID; public long id; void addListedArticle(Article article, int stock) { - this.imgPath = article.image.path; + + if (article.image != null) { + this.imgPath = article.image.path; + } this.title = article.title; - this.price_netto = String.format("%.2f", ((float) article.shopPricePerUnitNetCent / 100)); + this.priceNet = String.format("%.2f", ((float) article.shopPricePerUnitNetCent / 100)); this.price = String.format("%.2f", ((float) article.getPriceGross() / 100)); StringBuilder result = new StringBuilder(); @@ -221,7 +213,7 @@ public class InternArticleController { this.categorie = result.toString(); this.stock = stock; - this.offer_id = article.related.id; + this.offerID = article.related.id; this.id = article.id; } } @@ -231,116 +223,31 @@ public class InternArticleController { public String imgPath; public String title; public String price; - public String price_netto; + public String priceNet; public String reorderMaxPrice; public String categorie; public int stock; - public long offer_id; + public long offerID; public long id; public boolean shouldReorder; public String warehouseUnitsPerSlot; public String description; - - public String getImgPath() { - return imgPath; - } - - public void setImgPath(String imgPath) { - this.imgPath = imgPath; - } - - public String getTitle() { - return title; - } - - public void setTitle(String title) { - this.title = title; - } - - public String getPrice() { - return price; - } - - public void setPrice(String price) { - this.price = price; - } - - public String getPrice_netto() { - return price_netto; - } - - public void setPrice_netto(String price_netto) { - this.price_netto = price_netto; - } - - public String getReorderMaxPrice() { - return reorderMaxPrice; - } - - public void setReorderMaxPrice(String reorderMaxPrice) { - this.reorderMaxPrice = reorderMaxPrice; - } + public int vatPercent; public String getCategorie() { return categorie; } - public void setCategorie(String categorie) { - this.categorie = categorie; - } - - public int getStock() { - return stock; - } - - public void setStock(int stock) { - this.stock = stock; - } - - public long getOffer_id() { - return offer_id; - } - - public void setOffer_id(long offer_id) { - this.offer_id = offer_id; - } - - public long getId() { - return id; - } - - public void setId(long id) { - this.id = id; - } - - public boolean isShouldReorder() { - return shouldReorder; - } - - public void setShouldReorder(boolean shouldReorder) { - this.shouldReorder = shouldReorder; - } - - public String getWarehouseUnitsPerSlot() { - return warehouseUnitsPerSlot; - } - - public void setWarehouseUnitsPerSlot(String warehouseUnitsPerSlot) { - this.warehouseUnitsPerSlot = warehouseUnitsPerSlot; - } - public String getDescription() { return description; } - public void setDescription(String description) { - this.description = description; - } - void addArticle(Article article, int stock) { - this.imgPath = article.image.path; + if (article.image != null) { + this.imgPath = article.image.path; + } this.title = article.title; - this.price_netto = String.format("%.2f", ((float) article.shopPricePerUnitNetCent / 100)); + this.priceNet = String.format("%.2f", ((float) article.shopPricePerUnitNetCent / 100)); this.price = String.format("%.2f", ((float) article.getPriceGross() / 100)); StringBuilder result = new StringBuilder(); @@ -352,12 +259,13 @@ public class InternArticleController { this.categorie = result.toString(); this.stock = stock; - this.offer_id = article.related.id; + this.offerID = article.related.id; this.id = article.id; this.reorderMaxPrice = String.format("%.2f", ((float) article.reorderMaxPrice / 100)); this.shouldReorder = article.shouldReorder; this.warehouseUnitsPerSlot = String.valueOf(article.warehouseUnitsPerSlot); this.description = article.description; + this.vatPercent = article.related.vatPercent; } } diff --git a/prototype/src/main/java/org/hso/ecommerce/controller/intern/InternIndexController.java b/prototype/src/main/java/org/hso/ecommerce/controller/intern/InternIndexController.java index 65b3dba..43fe2d9 100644 --- a/prototype/src/main/java/org/hso/ecommerce/controller/intern/InternIndexController.java +++ b/prototype/src/main/java/org/hso/ecommerce/controller/intern/InternIndexController.java @@ -1,8 +1,34 @@ package org.hso.ecommerce.controller.intern; +import java.util.Optional; + +import org.hso.ecommerce.controller.intern.accounting.AccountingController; +import org.hso.ecommerce.entities.booking.BookingAccountEntry; +import org.hso.ecommerce.repos.booking.BookingAccountEntryRepository; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; @Controller -//@RequestMapping("...") +@RequestMapping("/intern") public class InternIndexController { + + @Autowired + private final BookingAccountEntryRepository bookingAccountEntryRepository = null; + + @GetMapping("/") + public String intern(Model model) { + Optional mainAccount = bookingAccountEntryRepository.getByMain(); + int mainAccountBalance = mainAccount.map(entry -> entry.newSumCent).orElse(0); + Optional vatAccount = bookingAccountEntryRepository.getByVat(); + int vatAccountBalance = vatAccount.map(entry -> entry.newSumCent).orElse(0); + + model.addAttribute("mainAccountBalance", AccountingController.fmtEuro(mainAccountBalance)); + model.addAttribute("vatAccountBalance", AccountingController.fmtEuro(vatAccountBalance)); + + return "intern/index"; + } + } diff --git a/prototype/src/main/java/org/hso/ecommerce/controller/intern/WarehouseController.java b/prototype/src/main/java/org/hso/ecommerce/controller/intern/WarehouseController.java index 9b618f7..4a0258e 100644 --- a/prototype/src/main/java/org/hso/ecommerce/controller/intern/WarehouseController.java +++ b/prototype/src/main/java/org/hso/ecommerce/controller/intern/WarehouseController.java @@ -1,8 +1,27 @@ package org.hso.ecommerce.controller.intern; +import org.hso.ecommerce.repos.warehouse.WarehouseBookingRepository; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; + +import javax.servlet.http.HttpServletRequest; @Controller -//@RequestMapping("...") +@RequestMapping("/intern/warehouse/") public class WarehouseController { + + @Autowired + private final WarehouseBookingRepository warehouseBookingRepository = null; + + @GetMapping("/") + public String accountingWarehouse( + Model model, + HttpServletRequest request + ) { + model.addAttribute("bookings", warehouseBookingRepository.findAll()); + return "intern/warehouse/index"; + } } diff --git a/prototype/src/main/java/org/hso/ecommerce/controller/intern/accounting/AccountingController.java b/prototype/src/main/java/org/hso/ecommerce/controller/intern/accounting/AccountingController.java new file mode 100644 index 0000000..c7f9b75 --- /dev/null +++ b/prototype/src/main/java/org/hso/ecommerce/controller/intern/accounting/AccountingController.java @@ -0,0 +1,223 @@ +package org.hso.ecommerce.controller.intern.accounting; + +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.List; + +import org.hso.ecommerce.entities.booking.Booking; +import org.hso.ecommerce.entities.booking.BookingAccountEntry; +import org.hso.ecommerce.entities.booking.BookingReason; +import org.hso.ecommerce.repos.booking.BookingRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.GetMapping; + +@Controller +public class AccountingController { + + @Autowired + private BookingRepository bookingRepository = null; + + /** + * A description used to render the html template for the overview of all bookings + */ + static class TemplateBooking { + public String datetime; + public String amount; + public String source; + public String sourceAddr; + public String sourceBalance; + public String destination; + public String destinationAddr; + public String destinationBalance; + public String reason; + public String reference; + public String referenceAddr; + } + + /** + * A description used to render the html template for bookings on a specific account + */ + public static class ShortTemplateBooking { + public String datetime; + public String amount; + public String source; + public String sourceAddr; + public String balance; + public String reason; + public String reference; + public String referenceAddr; + } + + public static class ShortTemplateBookingResult { + public final String balance; + public final List bookings; + + public ShortTemplateBookingResult(String balance, List bookings) { + this.balance = balance; + this.bookings = bookings; + } + } + + /** + * Used to check which side of the booking (source or destination) is the account we are currently looking at. + */ + public interface AccountFilter { + boolean matches(BookingAccountEntry account); + } + + /** + * Renders template information for the bookings of one specific account. + * + * @param bookings The (already fetched) booking entities to display + * @param currentAccount A filter matching the account that is to be displayed + * @return A collection result containing the final balance and all booking entries. + */ + public ShortTemplateBookingResult buildShortTemplate(List bookings, AccountFilter currentAccount) { + List templateBookings = new ArrayList<>(); + for (Booking booking : bookings) { + ShortTemplateBooking tb = new ShortTemplateBooking(); + tb.datetime = new SimpleDateFormat("dd.MM.yyyy HH:mm").format(booking.created); + tb.reason = booking.reason.comment; + tb.reference = describeReference(booking.reason); + tb.referenceAddr = linkToReference(booking.reason); + if (booking.destination != null && currentAccount.matches(booking.destination)) { + // Money was transferred onto the account we are looking at. + tb.amount = fmtEuro(booking.amountCent); + if (booking.source != null) { + tb.source = describeAccount(booking.source); + tb.sourceAddr = linkAddrOfAccount(booking.source); + } else { + tb.source = "-"; + tb.sourceAddr = null; + } + tb.balance = fmtEuro(booking.destination.newSumCent); + } else if (booking.source != null && currentAccount.matches(booking.source)) { + // Money was transferred away from the account we are looking at. + tb.amount = fmtEuro(-booking.amountCent); // Negative because of the transfer away + if (booking.destination != null) { + tb.source = describeAccount(booking.destination); // 'source' means 'the other account' in this case + tb.sourceAddr = linkAddrOfAccount(booking.destination); + } else { + tb.source = "-"; + tb.sourceAddr = null; + } + tb.balance = fmtEuro(booking.source.newSumCent); + } else { + throw new RuntimeException( + "This booking should not appear in this list, because neither source nor destination is the account we are looking at."); + } + templateBookings.add(tb); + } + + String balance = templateBookings.isEmpty() ? fmtEuro(0) : templateBookings.get(0).balance; + return new ShortTemplateBookingResult(balance, templateBookings); + } + + public static String fmtEuro(long amountCent) { + return String.format("%.2f EUR", amountCent / 100.0); + } + + private String describeAccount(BookingAccountEntry account) { + if (account.isMainAccount) { + return "Hauptkonto"; + } else if (account.isVATAccount) { + return "Mehrwertsteuer"; + } else if (account.supplierAccount != null) { + return "Lieferant " + account.supplierAccount.id; + } else if (account.userAccount != null) { + return "Kunde " + account.userAccount.id; + } else { + return "- unbekannt -"; + } + } + + private String linkAddrOfAccount(BookingAccountEntry account) { + if (account.isMainAccount) { + return "/intern/accounting/main"; + } else if (account.isVATAccount) { + return "/intern/accounting/vat"; + } else if (account.supplierAccount != null) { + return "/intern/suppliers/" + account.supplierAccount.id; + } else if (account.userAccount != null) { + return "/intern/customers/" + account.userAccount.id; + } else { + return null; + } + } + + private String describeReference(BookingReason reason) { + if (reason.customerOrder != null) { + return reason.customerOrder.id + ""; + } else if (reason.customerPayment != null) { + return "Bezahlung mit Kreditkarte " + reason.customerPayment.payment.creditCardNumber; + } else if (reason.supplierOrder != null) { + return "Lieferanten-Bestellung " + reason.supplierOrder.id; + } else { + return "-"; + } + } + + private String linkToReference(BookingReason reason) { + if (reason.customerOrder != null) { + return "/intern/customerOrders/" + reason.customerOrder.id; + } else { + return null; + } + } + + @GetMapping("/intern/accounting/") + public String accounting(Model model) { + List bookings = bookingRepository.allBookingsReverseChronologically(); + List templateBookings = new ArrayList<>(); + for (Booking booking : bookings) { + TemplateBooking tb = new TemplateBooking(); + tb.datetime = new SimpleDateFormat("dd.MM.yyyy HH:mm").format(booking.created); + tb.amount = fmtEuro(booking.amountCent); + if (booking.source != null) { + tb.source = describeAccount(booking.source); + tb.sourceAddr = linkAddrOfAccount(booking.source); + tb.sourceBalance = fmtEuro(booking.source.newSumCent); + } else { + tb.source = "-"; + tb.sourceAddr = null; + tb.sourceBalance = "-"; + } + if (booking.destination != null) { + tb.destination = describeAccount(booking.destination); + tb.destinationAddr = linkAddrOfAccount(booking.destination); + tb.destinationBalance = fmtEuro(booking.destination.newSumCent); + } else { + tb.destination = "-"; + tb.destinationAddr = null; + tb.destinationBalance = "-"; + } + tb.reason = booking.reason.comment; + tb.reference = describeReference(booking.reason); + tb.referenceAddr = linkToReference(booking.reason); + templateBookings.add(tb); + } + + model.addAttribute("bookings", templateBookings); + return "intern/accounting/index"; + } + + @GetMapping("/intern/accounting/vat") + public String accountingVat(Model model) { + List bookings = bookingRepository.vatBookingsReverseChronologically(); + ShortTemplateBookingResult result = buildShortTemplate(bookings, account -> account.isVATAccount); + model.addAttribute("balance", result.balance); + model.addAttribute("bookings", result.bookings); + return "intern/accounting/vat"; + } + + @GetMapping("/intern/accounting/main") + public String accountingIntern(Model model) { + List bookings = bookingRepository.mainBookingsReverseChronologically(); + ShortTemplateBookingResult result = buildShortTemplate(bookings, account -> account.isMainAccount); + model.addAttribute("balance", result.balance); + model.addAttribute("bookings", result.bookings); + return "intern/accounting/main"; + } +} diff --git a/prototype/src/main/java/org/hso/ecommerce/controller/intern/accounting/ManualAccountingController.java b/prototype/src/main/java/org/hso/ecommerce/controller/intern/accounting/ManualAccountingController.java new file mode 100644 index 0000000..fd820b1 --- /dev/null +++ b/prototype/src/main/java/org/hso/ecommerce/controller/intern/accounting/ManualAccountingController.java @@ -0,0 +1,270 @@ +package org.hso.ecommerce.controller.intern.accounting; + +import java.util.Optional; + +import org.hso.ecommerce.action.booking.CreateBookingAction; +import org.hso.ecommerce.entities.booking.Booking; +import org.hso.ecommerce.entities.booking.BookingAccountEntry; +import org.hso.ecommerce.entities.booking.BookingReason; +import org.hso.ecommerce.repos.booking.BookingAccountEntryRepository; +import org.hso.ecommerce.repos.booking.BookingRepository; +import org.hso.ecommerce.repos.supplier.SupplierRepository; +import org.hso.ecommerce.repos.user.UserRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.PostMapping; + +@Controller +public class ManualAccountingController { + + @Autowired + final BookingRepository bookingRepository = null; + + @Autowired + final BookingAccountEntryRepository bookingAccountEntryRepository = null; + + @Autowired + final UserRepository userRepository = null; + + @Autowired + final SupplierRepository supplierRepository = null; + + /** + * Collection for the form values used to create a manual booking + */ + public static class ManualAccounting { + String amount; + String source; + String sourceCustomer; + String sourceSupplier; + String destination; + String destinationCustomer; + String destinationSupplier; + String reason; + String reasonText; + + /** + * Default constructor with default values for the form + */ + public ManualAccounting() { + amount = "0.00"; + reason = "Manual"; + } + + public String getAmount() { + return amount; + } + + public void setAmount(String amount) { + this.amount = amount; + } + + public String getSource() { + return source; + } + + public void setSource(String source) { + this.source = source; + } + + public String getSourceCustomer() { + return sourceCustomer; + } + + public void setSourceCustomer(String sourceCustomer) { + this.sourceCustomer = sourceCustomer; + } + + public String getSourceSupplier() { + return sourceSupplier; + } + + public void setSourceSupplier(String sourceSupplier) { + this.sourceSupplier = sourceSupplier; + } + + public String getDestination() { + return destination; + } + + public void setDestination(String destination) { + this.destination = destination; + } + + public String getDestinationCustomer() { + return destinationCustomer; + } + + public void setDestinationCustomer(String destinationCustomer) { + this.destinationCustomer = destinationCustomer; + } + + public String getDestinationSupplier() { + return destinationSupplier; + } + + public void setDestinationSupplier(String destinationSupplier) { + this.destinationSupplier = destinationSupplier; + } + + public String getReason() { + return reason; + } + + public void setReason(String reason) { + this.reason = reason; + } + + public String getReasonText() { + return reasonText; + } + + public void setReasonText(String reasonText) { + this.reasonText = reasonText; + } + } + + /** + * An exception to represent errors that can be shown to the user + */ + public static class InvalidFormDataException extends Exception { + public InvalidFormDataException(String msg) { + super(msg); + } + + private static final long serialVersionUID = 1L; + } + + private boolean sameAccountBothSides(ManualAccounting formData) { + // No need to check for NumberFormatException because the numbers were already parsed before. + if (!formData.getSource().equals(formData.getDestination())) { + return false; + } else if (formData.getSource().equals("Cust") + && Long.parseLong(formData.getSourceCustomer()) != Long.parseLong(formData.getDestinationCustomer())) { + return false; + } else if (formData.getSource().equals("Sup") + && Long.parseLong(formData.getSourceSupplier()) != Long.parseLong(formData.getDestinationSupplier())) { + return false; + } else { + return true; + } + } + + public Booking createBooking(ManualAccounting formData) throws InvalidFormDataException { + if (formData.getSource() == null) { + throw new InvalidFormDataException("Bitte wählen Sie ein Quellkonto aus."); + } else if (formData.getDestination() == null) { + throw new InvalidFormDataException("Bitte wählen Sie ein Zielkonto aus."); + } + BookingAccountEntry source = getAccountFromFormData(formData.getSource(), formData.getSourceCustomer(), + formData.getSourceSupplier()); + BookingAccountEntry destination = getAccountFromFormData(formData.getDestination(), + formData.getDestinationCustomer(), formData.getDestinationSupplier()); + + if (sameAccountBothSides(formData)) { + throw new InvalidFormDataException("Quell- und Zielkonto dürfen nicht das selbe sein."); + } + + double doubleAmount; + try { + doubleAmount = Double.parseDouble(formData.amount); + } catch (NumberFormatException e) { + throw new InvalidFormDataException("Der angegebene Betrag ist ungültig."); + } + int amountCent = (int) Math.round(doubleAmount * 100); + + BookingReason reason = new BookingReason(); + if (formData.getReason().equals("Start")) { + reason.isStartBooking = true; + } else if (formData.getReason().equals("Manual")) { + reason.isManuel = true; + } else { + throw new RuntimeException("Invalid form value for the booking reason: " + formData.getReason()); + } + reason.comment = formData.reasonText; + + CreateBookingAction action = new CreateBookingAction(source, destination, reason, amountCent); + return action.finish(); + } + + /** + * Retrieve the corresponding account based on user-input + * + * @param account The chosen value on the radio buttons + * @param customer The given customer id from the corresponding text field + * @param supplier the given supplier id from the corresponding text field + * @return The account entry that can be used to create the new booking + * @throws InvalidFormDataException If the user provided incorrect data in any way + */ + private BookingAccountEntry getAccountFromFormData(String account, String customer, String supplier) + throws InvalidFormDataException { + if (account.equals("None")) { + return null; + } else if (account.equals("Main")) { + return bookingAccountEntryRepository.getByMain().orElseGet(BookingAccountEntry::newMain); + } else if (account.equals("Vat")) { + return bookingAccountEntryRepository.getByVat().orElseGet(BookingAccountEntry::newVat); + } else if (account.equals("Cust")) { + long userId; + try { + userId = Long.parseLong(customer); + } catch (NumberFormatException e) { + throw new InvalidFormDataException("Die angegebene Kunden-Nr. ist ungültig."); + } + Optional bookingAccount = bookingAccountEntryRepository.getByUser(userId); + if (!bookingAccount.isPresent()) { + bookingAccount = userRepository.findById(userId).map((user) -> BookingAccountEntry.newUser(user)); + } + if (bookingAccount.isPresent()) { + return bookingAccount.get(); + } else { + throw new InvalidFormDataException("Der Kunde Nr. " + userId + " konnte nicht gefunden werden."); + } + } else if (account.equals("Sup")) { + long supplierId; + try { + supplierId = Long.parseLong(supplier); + } catch (NumberFormatException e) { + throw new InvalidFormDataException("Die angegebene Lieferanten-Nr. ist ungültig."); + } + Optional bookingAccount = bookingAccountEntryRepository.getBySupplier(supplierId); + if (!bookingAccount.isPresent()) { + bookingAccount = supplierRepository.findById(supplierId) + .map((sup) -> BookingAccountEntry.newSupplier(sup)); + } + if (bookingAccount.isPresent()) { + return bookingAccount.get(); + } else { + throw new InvalidFormDataException( + "Der Lieferant Nr. " + supplierId + " konnte nicht gefunden werden."); + } + } else { + throw new RuntimeException("Invalid form value for an account: " + account); + } + } + + @GetMapping("/intern/accounting/addManual") + public String accountingAddManual(Model model) { + model.addAttribute("form_vals", new ManualAccounting()); + return "intern/accounting/addManual"; + } + + @PostMapping("/intern/accounting/addManual") + public String accountingAddManualSubmit(Model model, @ModelAttribute ManualAccounting formData) { + Booking booking; + try { + booking = createBooking(formData); + bookingRepository.save(booking); + model.addAttribute("info", "Die Buchung wurde erfolgreich erstellt."); + model.addAttribute("form_vals", new ManualAccounting()); // Reply with empty form on success + } catch (InvalidFormDataException e) { + model.addAttribute("error", e.getMessage()); + model.addAttribute("form_vals", formData); + } + return "intern/accounting/addManual"; + } + +} diff --git a/prototype/src/main/java/org/hso/ecommerce/controller/intern/customers/CustomerOrderController.java b/prototype/src/main/java/org/hso/ecommerce/controller/intern/customers/CustomerOrderController.java index dc44655..621d906 100644 --- a/prototype/src/main/java/org/hso/ecommerce/controller/intern/customers/CustomerOrderController.java +++ b/prototype/src/main/java/org/hso/ecommerce/controller/intern/customers/CustomerOrderController.java @@ -4,7 +4,8 @@ import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import org.hso.ecommerce.api.RestServiceForDelivery; import org.hso.ecommerce.entities.shop.CustomerOrder; -import org.hso.ecommerce.repos.shop.CustomerOderRepository; + +import org.hso.ecommerce.repos.shop.CustomerOrderRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.format.datetime.DateFormatterRegistrar; import org.springframework.stereotype.Controller; @@ -27,7 +28,7 @@ import java.util.stream.Collectors; public class CustomerOrderController { @Autowired - private final CustomerOderRepository customerOrderRepository = null; + private final CustomerOrderRepository customerOrderRepository = null; @Autowired private final RestServiceForDelivery restServiceForDelivery = null; diff --git a/prototype/src/main/java/org/hso/ecommerce/controller/intern/customers/CustomersIndexController.java b/prototype/src/main/java/org/hso/ecommerce/controller/intern/customers/CustomersIndexController.java index a15b927..3432770 100644 --- a/prototype/src/main/java/org/hso/ecommerce/controller/intern/customers/CustomersIndexController.java +++ b/prototype/src/main/java/org/hso/ecommerce/controller/intern/customers/CustomersIndexController.java @@ -1,8 +1,120 @@ package org.hso.ecommerce.controller.intern.customers; +import java.util.List; + +import javax.servlet.http.HttpServletRequest; + +import org.hso.ecommerce.controller.intern.accounting.AccountingController; +import org.hso.ecommerce.controller.intern.accounting.AccountingController.ShortTemplateBookingResult; +import org.hso.ecommerce.entities.booking.Booking; +import org.hso.ecommerce.entities.shop.CustomerOrder; +import org.hso.ecommerce.entities.user.User; +import org.hso.ecommerce.repos.booking.BookingRepository; +import org.hso.ecommerce.repos.shop.CustomerOrderRepository; +import org.hso.ecommerce.repos.user.UserRepository; +import org.springframework.beans.factory.annotation.Autowired; + import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletResponse; +import java.util.Optional; @Controller -//@RequestMapping("...") +@RequestMapping("/intern/customers") public class CustomersIndexController { + + @Autowired + private BookingRepository bookingRepository = null; + + @Autowired + private final CustomerOrderRepository customerOrderRepository = null; + + @Autowired + private final UserRepository userRepository = null; + + @Autowired + private AccountingController accountingController = null; + + @GetMapping("") + public String internCustomers(Model model) { + List users = userRepository.findAll(); + + model.addAttribute("users", users); + + return "intern/customers/index"; + } + + @GetMapping("/{id}") + public String internCustomersId(Model model, + @PathVariable("id") Long id, + HttpServletResponse response, + HttpServletRequest request + ) { + Optional optUser = userRepository.findById(id); + if (!optUser.isPresent()) { + request.setAttribute("error", "Der User wurde nicht gefunden."); + response.setStatus(HttpServletResponse.SC_NOT_FOUND); + return "error/404"; + } + User user = optUser.get(); + model.addAttribute("user", user); + + List orders = customerOrderRepository.getOrdersByUserId(id); + model.addAttribute("orders", orders); + + List bookings = bookingRepository.customerBookingsReverseChronologically(id); + ShortTemplateBookingResult result = accountingController.buildShortTemplate( + bookings, + account -> account.userAccount != null && account.userAccount.id == id); + model.addAttribute("balance", result.balance); + model.addAttribute("bookings", result.bookings); + + return "intern/customers/id"; + } + + @PostMapping("/{id}/changeState") + public String changeState(@PathVariable("id") Long id, + @RequestParam(value = "active", required = false) String active, + @RequestParam(value = "ma", required = false) String ma + ) { + User user = userRepository.findById(id).get(); + + if (active == null) + user.isActive = false; + else + user.isActive = true; + + if (ma == null) + user.isEmployee = false; + else + user.isEmployee = true; + + userRepository.save(user); + + return "redirect:/intern/customers/" + id.toString(); + } + + @PostMapping("/{id}/resetPassword") + public String resetPassword(@PathVariable("id") Long id, + @RequestParam("password") String password, + @RequestParam("password2") String password2, + HttpServletRequest request + ) { + if (!password.equals(password2)) { + request.setAttribute("error", "Passwörter stimmen nicht überein!"); + return "/intern/customers/id"; + } + User user = userRepository.findById(id).get(); + if (!user.validatePassword(password)) { + request.setAttribute("error", "Die Passwörter stimmen nicht mit dem Original überein!"); + return "/intern/customers/id"; + } + user.setPassword("12345"); + userRepository.save(user); + request.setAttribute("info", "Passwort wurde auf 12345 geändert!"); + + return "/intern/customers/id"; + } } diff --git a/prototype/src/main/java/org/hso/ecommerce/controller/intern/suppliers/SupplierIndexController.java b/prototype/src/main/java/org/hso/ecommerce/controller/intern/suppliers/SupplierIndexController.java index d6cefc0..e8881fd 100644 --- a/prototype/src/main/java/org/hso/ecommerce/controller/intern/suppliers/SupplierIndexController.java +++ b/prototype/src/main/java/org/hso/ecommerce/controller/intern/suppliers/SupplierIndexController.java @@ -1,8 +1,157 @@ package org.hso.ecommerce.controller.intern.suppliers; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +import org.hso.ecommerce.controller.intern.accounting.AccountingController; +import org.hso.ecommerce.controller.intern.accounting.AccountingController.ShortTemplateBooking; +import org.hso.ecommerce.controller.intern.accounting.AccountingController.ShortTemplateBookingResult; +import org.hso.ecommerce.entities.booking.Booking; +import org.hso.ecommerce.entities.supplier.Supplier; +import org.hso.ecommerce.entities.supplier.SupplierOrder; +import org.hso.ecommerce.repos.booking.BookingRepository; +import org.hso.ecommerce.repos.supplier.SupplierOrderRepository; +import org.hso.ecommerce.repos.supplier.SupplierRepository; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; @Controller -//@RequestMapping("...") +@RequestMapping("/intern/") public class SupplierIndexController { + + @Autowired + private final SupplierRepository supplierRepository = null; + + @Autowired + private final SupplierOrderRepository supplierOrderRepository = null; + + @Autowired + private final BookingRepository bookingRepository = null; + + @Autowired + private final AccountingController accountingController = null; + + @GetMapping("suppliers") + public String listSuppliers(Model model) { + + List totals = new ArrayList(); + + for (Supplier supplier : supplierRepository.findAll()) { + UImodelSuppliers tmp = new UImodelSuppliers(supplier.id, supplier.name); + totals.add(tmp); + } + + model.addAttribute("suppliers", totals); + return "intern/suppliers/index"; + } + + @GetMapping("/suppliers/{id}") + public String supplierDetail(Model model, @PathVariable String id) { + + long supplierId = Long.parseLong(id); + + // add orders from supplier to UImodel + List orders = new ArrayList(); + for (SupplierOrder supplierOrder : supplierOrderRepository.findOrderBySupplierID(supplierId)) { + orders.add(new UImodelSupplierDetailOrders(supplierOrder)); + } + + // Table of bookings + List bookings = bookingRepository.supplierBookingsReverseChronologically(supplierId); + ShortTemplateBookingResult bookingResult = accountingController.buildShortTemplate(bookings, + account -> account.supplierAccount != null && account.supplierAccount.id == supplierId); + + UImodelSupplierDetail total = new UImodelSupplierDetail(supplierRepository.findSupplierById(supplierId).name, + bookingResult.balance, orders, bookingResult.bookings); + + model.addAttribute("SupplierDetail", total); + + return "intern/suppliers/id"; + } + + public class UImodelSuppliers { + public long id; + public String name; + + public UImodelSuppliers(long id, String name) { + this.id = id; + this.name = name; + } + + } + + public class UImodelSupplierDetail { + + public String name; + public String balance; + public List orders; + public List bookings; + + public UImodelSupplierDetail(String name, String balance, List orders, + List bookings + ) { + this.name = name; + this.balance = balance; + this.orders = orders; + this.bookings = bookings; + } + + } + + public class UImodelSupplierDetailOrders { + public long id; + public String dateOrder; + public String articleName; + public long articleId; + public String priceNet; + public String quantity; + public String priceTotal; + public boolean arrived; + + public UImodelSupplierDetailOrders(SupplierOrder order) { + this.id = order.id; + this.articleName = order.ordered.title; + this.articleId = order.ordered.id; + this.priceNet = String.format("%.2f", ((float) order.pricePerUnitNetCent / 100)); + this.quantity = String.valueOf(order.numberOfUnits); + this.priceTotal = String.format("%.2f", ((float) order.totalPriceNet / 100)); + + Date date = new Date(); + date.setTime(order.created.getTime()); + this.dateOrder = new SimpleDateFormat("dd.MM.yyyy").format(date); + + if (order.delivered != null) { + arrived = true; + } else { + arrived = false; + } + } + } + + public class UImodelSupplierDetailBookings { + + public String dateBooking; + public String price; + public String srcName; + public String balance; + public String reason; + public long orderID; + + public UImodelSupplierDetailBookings(Booking booking) { + Date date = new Date(); + date.setTime(booking.reason.supplierOrder.created.getTime()); + this.dateBooking = new SimpleDateFormat("dd.MM.yyyy").format(date); + this.price = String.format("%.2f", ((float) booking.amountCent / 100)); + this.srcName = ((booking.source.isMainAccount) ? "Hauptkonto" : booking.source.supplierAccount.name); + this.balance = String.format("%.2f", ((float) booking.destination.newSumCent / 100)); + this.reason = booking.reason.comment; + this.orderID = booking.reason.supplierOrder.id; + } + } } diff --git a/prototype/src/main/java/org/hso/ecommerce/controller/intern/suppliers/SupplierOfferController.java b/prototype/src/main/java/org/hso/ecommerce/controller/intern/suppliers/SupplierOfferController.java index 3ef21bf..98a4c8b 100644 --- a/prototype/src/main/java/org/hso/ecommerce/controller/intern/suppliers/SupplierOfferController.java +++ b/prototype/src/main/java/org/hso/ecommerce/controller/intern/suppliers/SupplierOfferController.java @@ -26,11 +26,11 @@ public class SupplierOfferController { @GetMapping("supplierOffers") public String internListedArticles(Model model) { - List totals = new ArrayList(); + List totals = new ArrayList<>(); for (ArticleOffer article : offersRepository.findAll()) { - UImodelOfferedArticle tmp = new UImodelOfferedArticle(); - tmp.addData(article, "supplierName01", 4884, articleRepository.findArticleIDByRelatedID(article.id)); //TODO display supplier name with link + UImodelOfferedArticle tmp = new UImodelOfferedArticle(article, + articleRepository.findArticleIDByRelatedID(article.id)); totals.add(tmp); } @@ -40,106 +40,27 @@ public class SupplierOfferController { public class UImodelOfferedArticle { - long offer_id; - String title; - String manufacturer; - String articlenumber; - String supplierName; - int supplierId; - String price; - String ads; - int listedArticleId; - boolean offerIsListed; //true --> offered article is listed + public long offerId; + public String title; + public String manufacturer; + public String articleNumber; + public String supplierName; + public String price; + public String ads; + public int listedArticleId; + public boolean offerIsListed; // true --> offered article is listed - public long getOffer_id() { - return offer_id; - } + public UImodelOfferedArticle(ArticleOffer article, Optional listedArticleId) { - public void setOffer_id(long offer_id) { - this.offer_id = offer_id; - } - - public boolean isOfferIsListed() { - return offerIsListed; - } - - public void setOfferIsListed(boolean offerIsListed) { - this.offerIsListed = offerIsListed; - } - - public String getTitle() { - return title; - } - - public void setTitle(String title) { - this.title = title; - } - - public String getManufacturer() { - return manufacturer; - } - - public void setManufacturer(String manufacturer) { - this.manufacturer = manufacturer; - } - - public String getArticlenumber() { - return articlenumber; - } - - public void setArticlenumber(String articlenumber) { - this.articlenumber = articlenumber; - } - - public String getSupplierName() { - return supplierName; - } - - public void setSupplierName(String supplierName) { - this.supplierName = supplierName; - } - - public int getSupplierId() { - return supplierId; - } - - public void setSupplierId(int supplierId) { - this.supplierId = supplierId; - } - - public String getPrice() { - return price; - } - - public void setPrice(String price) { - this.price = price; - } - - public String getAds() { - return ads; - } - - public void setAds(String ads) { - this.ads = ads; - } - - public int getListedArticleId() { - return listedArticleId; - } - - public void setListedArticleId(int listedArticleId) { - this.listedArticleId = listedArticleId; - } - - public void addData(ArticleOffer article, String supplierName, int supplierId, - Optional listedArticleId) { - - this.offer_id = article.id; + this.offerId = article.id; this.title = article.title; this.manufacturer = article.manufacturer; - this.articlenumber = article.articleNumber; - this.supplierName = supplierName; - this.supplierId = supplierId; + this.articleNumber = article.articleNumber; + if (article.cheapestSupplier != null) { + this.supplierName = article.cheapestSupplier.name; + } else { + this.supplierName = "-"; + } this.price = String.format("%.2f", ((float) article.pricePerUnitNet / 100)); this.ads = (article.shouldBeAdvertised) ? "Ja" : "Nein"; diff --git a/prototype/src/main/java/org/hso/ecommerce/controller/intern/suppliers/SupplierOrderController.java b/prototype/src/main/java/org/hso/ecommerce/controller/intern/suppliers/SupplierOrderController.java index ef3acb4..3259a17 100644 --- a/prototype/src/main/java/org/hso/ecommerce/controller/intern/suppliers/SupplierOrderController.java +++ b/prototype/src/main/java/org/hso/ecommerce/controller/intern/suppliers/SupplierOrderController.java @@ -1,8 +1,135 @@ package org.hso.ecommerce.controller.intern.suppliers; +import org.hso.ecommerce.action.warehouse.SupplierOrderArrivedAction; +import org.hso.ecommerce.entities.shop.Article; +import org.hso.ecommerce.entities.supplier.SupplierOrder; +import org.hso.ecommerce.entities.warehouse.WarehouseBookingPositionSlotEntry; +import org.hso.ecommerce.repos.shop.ArticleRepository; +import org.hso.ecommerce.repos.supplier.SupplierOrderRepository; +import org.hso.ecommerce.repos.warehouse.SlotRepository; +import org.hso.ecommerce.repos.warehouse.WarehouseBookingPositionSlotEntryRepository; +import org.hso.ecommerce.repos.warehouse.WarehouseBookingRepository; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; + +import javax.servlet.http.HttpServletResponse; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.stream.Collectors; @Controller -//@RequestMapping("...") +@RequestMapping("/intern/") public class SupplierOrderController { + + @Autowired + private final SupplierOrderRepository supplierOrderRepository = null; + + @Autowired + private final ArticleRepository articleRepository = null; + + @Autowired + private final WarehouseBookingPositionSlotEntryRepository warehouseBookingPositionSlotEntryRepository = null; + + @Autowired + private final WarehouseBookingRepository warehouseBookingRepository = null; + + @Autowired + private final SlotRepository slotRepository = null; + + @GetMapping("supplierOrders") + public String listSuppliers(Model model) { + + List totals = new ArrayList(); + + for (SupplierOrder order : supplierOrderRepository.findAll()) { + final Article article = articleRepository.findArticleByArticleOffer(order.ordered).orElse(null); + totals.add(new UImodelSupplierOrder(order, article)); + } + + model.addAttribute("orders", totals); + + return "intern/supplierOrders/index"; + } + + @PostMapping("/supplierOrders/store/{id}") + public String storeOrder(@PathVariable("id") Long supplierOrderID, Model model, HttpServletResponse response) { + SupplierOrder order = supplierOrderRepository.findById(supplierOrderID).orElse(null); + if (order == null) { + model.addAttribute("error", "Die ausgewählte Lieferung konnte nicht gefunden werden."); + response.setStatus(HttpServletResponse.SC_EXPECTATION_FAILED); + return listSuppliers(model); + } + if (order.wasDelivered()) { + model.addAttribute("error", "Die ausgewählte Lieferung wurde schon zugestellt."); + response.setStatus(HttpServletResponse.SC_EXPECTATION_FAILED); + return listSuppliers(model); + } + + + final Article article = articleRepository.findArticleByArticleOffer(order.ordered).orElse(null); + if (article == null) { + model.addAttribute("error", "Der bestellte Artikel wurde nicht angelegt, er hätte nicht bestellt werden dürfen."); + response.setStatus(HttpServletResponse.SC_EXPECTATION_FAILED); + return listSuppliers(model); + } + + // Hard to do efficiently, this should be fine. + List candidates = slotRepository + .findAll() + .stream() + .map(slot -> + warehouseBookingPositionSlotEntryRepository.getBySlotNum(slot.slotNum).orElseGet(() -> + WarehouseBookingPositionSlotEntry.empty(article, slot) + ) + ) + .filter(entry -> entry.article.id == article.id || entry.newSumSlot == 0) + .collect(Collectors.toList()); + + SupplierOrderArrivedAction action = new SupplierOrderArrivedAction(candidates, order, article); + + try { + SupplierOrderArrivedAction.Result result = action.finish(); + supplierOrderRepository.save(result.getOrder()); + warehouseBookingRepository.save(result.getBooking()); + } catch (SupplierOrderArrivedAction.NoSpaceInWarehouseException e) { + e.printStackTrace(); + } + + return "redirect:/intern/warehouse/todo"; + } + + public class UImodelSupplierOrder { + public long id; + public String dateOrder; + public String supplierName; + public String articleName; + public long articleId; + public String priceNet; + public String quantity; + public String priceTotal; + public boolean arrived; + + public UImodelSupplierOrder(SupplierOrder order, Article article) { + this.id = order.id; + this.supplierName = order.supplier.name; + this.articleName = article != null ? article.title : "error"; + this.articleId = article != null ? article.id : 0; + this.priceNet = String.format("%.2f", ((float) order.pricePerUnitNetCent / 100)); + this.quantity = String.valueOf(order.numberOfUnits); + this.priceTotal = String.format("%.2f", ((float) order.totalPriceNet / 100)); + + Date date = new Date(); + date.setTime(order.created.getTime()); + this.dateOrder = new SimpleDateFormat("dd.MM.yyyy").format(date); + + arrived = order.delivered != null; + } + } } diff --git a/prototype/src/main/java/org/hso/ecommerce/controller/intern/warehouse/ManuelBookingController.java b/prototype/src/main/java/org/hso/ecommerce/controller/intern/warehouse/ManuelBookingController.java new file mode 100644 index 0000000..7ef8e0e --- /dev/null +++ b/prototype/src/main/java/org/hso/ecommerce/controller/intern/warehouse/ManuelBookingController.java @@ -0,0 +1,140 @@ +package org.hso.ecommerce.controller.intern.warehouse; + +import org.hso.ecommerce.action.warehouse.CreateManuelBookingAction; +import org.hso.ecommerce.entities.shop.Article; +import org.hso.ecommerce.entities.warehouse.Slot; +import org.hso.ecommerce.entities.warehouse.WarehouseBookingPositionSlotEntry; +import org.hso.ecommerce.repos.shop.ArticleRepository; +import org.hso.ecommerce.repos.warehouse.SlotRepository; +import org.hso.ecommerce.repos.warehouse.WarehouseBookingPositionSlotEntryRepository; +import org.hso.ecommerce.repos.warehouse.WarehouseBookingRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.util.Optional; + +@Controller +@RequestMapping("/intern/warehouse/") +public class ManuelBookingController { + + @Autowired + private final ArticleRepository articleRepository = null; + + @Autowired + private final SlotRepository slotRepository = null; + + @Autowired + private final WarehouseBookingPositionSlotEntryRepository warehouseBookingPositionSlotEntryRepository = null; + + @Autowired + private final WarehouseBookingRepository warehouseBookingRepository = null; + + @GetMapping("addManual") + public String warehouseAddManual( + Model model + ) { + + model.addAttribute("articles", articleRepository.findAll()); + model.addAttribute("slots", slotRepository.findAll()); + + return "intern/warehouse/addManual"; + } + + @PostMapping("addManual") + public String warehouseAddMaualPost( + Model model, + HttpServletRequest request, + HttpServletResponse response, + @RequestParam("articleId") String articleIdText, + @RequestParam("amount") Integer amount, + @RequestParam("reason") String reason, + @RequestParam("sourceIsSlot") Boolean sourceIsSlot, + @RequestParam("sourceSlot") Integer sourceSlotNum, + @RequestParam("destinationIsSlot") Boolean destinationIsSlot, + @RequestParam("destinationSlot") Integer destinationSlotNum + ) { + + // The suggestions for articleId in the UI show articles names, seperated by a " - ". + // The Number must be extracted first. + long articleId = -1; + try { + articleId = Long.parseLong(articleIdText.split(" - ", 2)[0].trim()); + } catch (NumberFormatException e) { + model.addAttribute("error", "Die Artikel Id konnte nicht erkannt werden."); + response.setStatus(HttpServletResponse.SC_BAD_REQUEST); + return "intern/warehouse/addManual"; + } + + + Optional
optionalArticle = articleRepository.findById(articleId); + Article article = null; + if (!optionalArticle.isPresent()) { + model.addAttribute("error", "Der Artikel konnte nicht gefunden werden."); + response.setStatus(HttpServletResponse.SC_EXPECTATION_FAILED); + return "intern/warehouse/addManual"; + } else { + article = optionalArticle.get(); + } + + if (amount <= 0) { + model.addAttribute("error", "Eine Anzahl <= 0 kann nicht verbucht werden."); + response.setStatus(HttpServletResponse.SC_EXPECTATION_FAILED); + return "intern/warehouse/addManual"; + } + + if (sourceIsSlot == false && destinationIsSlot == false) { + model.addAttribute("error", "Jede Buchung benötigt ein Ziel oder eine Quelle."); + response.setStatus(HttpServletResponse.SC_EXPECTATION_FAILED); + return "intern/warehouse/addManual"; + } + + Optional sourceSlot = Optional.empty(); + if (sourceIsSlot == true) { + sourceSlot = warehouseBookingPositionSlotEntryRepository.getBySlotNum(sourceSlotNum); + if (!sourceSlot.isPresent()) { + request.setAttribute("error", "Quelllagerplatz wurde nicht gefunden oder ist leer."); + response.setStatus(HttpServletResponse.SC_EXPECTATION_FAILED); + return "intern/warehouse/addManual"; + } + } + + Optional destinationSlot = Optional.empty(); + if (destinationIsSlot == true) { + Optional slot = slotRepository.findBySlotNum(destinationSlotNum); + if (!slot.isPresent()) { + request.setAttribute("error", "Ziellagerplatz wurde nicht gefunden."); + response.setStatus(HttpServletResponse.SC_EXPECTATION_FAILED); + return "intern/warehouse/addManual"; + } + + Article finalArticle = article; + destinationSlot = Optional.of(warehouseBookingPositionSlotEntryRepository.getBySlotNum(destinationSlotNum).orElseGet( + () -> WarehouseBookingPositionSlotEntry.empty(finalArticle, slot.get()) + )); + } + + try { + warehouseBookingRepository.save( + new CreateManuelBookingAction(article, amount, sourceSlot, destinationSlot, reason).finish() + ); + } catch (CreateManuelBookingAction.ArticleSlotConstraintArticleTypeFailedException e) { + model.addAttribute("error", "Es befindet sich der falsche Artikeltyp in Quell- oder Ziellagerplatz. "); + response.setStatus(HttpServletResponse.SC_EXPECTATION_FAILED); + return "intern/warehouse/addManual"; + } catch (CreateManuelBookingAction.ArticleSlotConstraintFailedException e) { + model.addAttribute("error", "Die maximale Anzahl an lagerbaren Artikeln im Ziellagerplatz wurde überschritten."); + response.setStatus(HttpServletResponse.SC_EXPECTATION_FAILED); + return "intern/warehouse/addManual"; + } + + return "redirect:/intern/warehouse/todo"; + } + +} diff --git a/prototype/src/main/java/org/hso/ecommerce/controller/intern/warehouse/SlotsController.java b/prototype/src/main/java/org/hso/ecommerce/controller/intern/warehouse/SlotsController.java new file mode 100644 index 0000000..8cc5721 --- /dev/null +++ b/prototype/src/main/java/org/hso/ecommerce/controller/intern/warehouse/SlotsController.java @@ -0,0 +1,46 @@ +package org.hso.ecommerce.controller.intern.warehouse; + +import org.hso.ecommerce.action.warehouse.CalculateWarehouseStatsAction; +import org.hso.ecommerce.entities.warehouse.WarehouseBookingPositionSlotEntry; +import org.hso.ecommerce.repos.warehouse.SlotRepository; +import org.hso.ecommerce.repos.warehouse.WarehouseBookingPositionSlotEntryRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; + +import javax.servlet.http.HttpServletRequest; +import java.util.List; +import java.util.stream.Collectors; + +@Controller +@RequestMapping("/intern/warehouse/") +public class SlotsController { + + @Autowired + private final WarehouseBookingPositionSlotEntryRepository warehouseBookingPositionSlotEntryRepository = null; + + @Autowired + private final SlotRepository slotRepository = null; + + @GetMapping("slots/") + public String accountingWarehouseSlots( + Model model, + HttpServletRequest request + ) { + + // Doing this in a single would be hard and error prone. + // Writing native queries should be minimized. + // Therefore this method was prefered + List entries = slotRepository.findAll().stream().map( + s -> warehouseBookingPositionSlotEntryRepository + .getBySlotNum(s.slotNum) + .orElseGet(() -> WarehouseBookingPositionSlotEntry.empty(null, s)) + ).collect(Collectors.toList()); + model.addAttribute("entries", entries); + + model.addAttribute("stats", new CalculateWarehouseStatsAction(entries).finish()); + return "intern/warehouse/slots/index"; + } +} diff --git a/prototype/src/main/java/org/hso/ecommerce/controller/intern/warehouse/TodoController.java b/prototype/src/main/java/org/hso/ecommerce/controller/intern/warehouse/TodoController.java new file mode 100644 index 0000000..4bed5cd --- /dev/null +++ b/prototype/src/main/java/org/hso/ecommerce/controller/intern/warehouse/TodoController.java @@ -0,0 +1,112 @@ +package org.hso.ecommerce.controller.intern.warehouse; + +import org.hso.ecommerce.action.shop.EnableTrackingAction; +import org.hso.ecommerce.entities.warehouse.WarehouseBooking; +import org.hso.ecommerce.repos.warehouse.WarehouseBookingRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.util.Optional; + +@Controller +@RequestMapping("/intern/warehouse/") +public class TodoController { + + @Autowired + private final WarehouseBookingRepository warehouseBookingRepository = null; + + @GetMapping("todo") + public String accountingWarehouseTodo( + Model model + ) { + model.addAttribute("bookings", warehouseBookingRepository.findNotDone()); + return "intern/warehouse/todo"; + } + + + @PostMapping("progress/{id}") + public String postProgressId( + Model model, + HttpServletRequest request, + HttpServletResponse response, + @PathVariable("id") Long id + ) { + Optional booking = warehouseBookingRepository.findById(id); + if (!booking.isPresent()) { + model.addAttribute("error", "Die Buchung wurde nicht gefunden."); + response.setStatus(HttpServletResponse.SC_BAD_REQUEST); + return "error/404"; + } + + if (booking.get().isInProgress) { + response.setStatus(409); + return "intern/warehouse/error_progress_failed"; + } + + booking.get().isInProgress = true; + warehouseBookingRepository.save(booking.get()); + + return "redirect:/intern/warehouse/progress/" + id; + } + + @PostMapping("progress/{id}/finish") + public String postProgressIdFinish( + Model model, + HttpServletRequest request, + HttpServletResponse response, + @PathVariable("id") Long id + ) { + Optional booking = warehouseBookingRepository.findById(id); + if (!booking.isPresent()) { + model.addAttribute("error", "Die Buchung wurde nicht gefunden."); + response.setStatus(HttpServletResponse.SC_BAD_REQUEST); + return "error/404"; + } + + booking.get().isInProgress = true; + booking.get().isDone = true; + + // Update Delivery Date + if (booking.get().reason.customerOrder != null) { + EnableTrackingAction.addTrackingInfo(booking.get().reason.customerOrder); + } + + warehouseBookingRepository.save(booking.get()); + + return "redirect:/intern/warehouse/todo"; + } + + @GetMapping("progress/{id}") + public String getProgressId(Model model, + HttpServletRequest request, + HttpServletResponse response, + @PathVariable("id") Long id) { + Optional booking = warehouseBookingRepository.findById(id); + if (!booking.isPresent()) { + model.addAttribute("error", "Die Buchung wurde nicht gefunden."); + response.setStatus(HttpServletResponse.SC_BAD_REQUEST); + return "error/404"; + } + + if (booking.get().isDone) { + model.addAttribute("info", "Die Buchung wurde schon abgeschlossen."); + } + + if (!booking.get().isInProgress) { + // Only reachable if path is manipulated. + model.addAttribute("error", "Die Buchung wurde noch nicht zugewiesen!"); + } + + model.addAttribute("booking", booking.get()); + return "intern/warehouse/id_progress"; + } + + +} diff --git a/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopArticleController.java b/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopArticleController.java index 235669c..18144f7 100644 --- a/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopArticleController.java +++ b/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopArticleController.java @@ -100,8 +100,11 @@ public class ShopArticleController { @PathVariable("id") Long id ) throws IOException { Article article = articleRepository.findArticleById(id); - InputStream in = new FileInputStream(article.image.path); - response.setContentType(MediaType.IMAGE_JPEG_VALUE); - IOUtils.copy(in, response.getOutputStream()); + + if(article.image != null) { + InputStream in = new FileInputStream(article.image.path); + response.setContentType(MediaType.IMAGE_JPEG_VALUE); + IOUtils.copy(in, response.getOutputStream()); + } } } \ No newline at end of file diff --git a/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopCheckoutController.java b/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopCheckoutController.java index 5481b3c..8b0b1ba 100644 --- a/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopCheckoutController.java +++ b/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopCheckoutController.java @@ -1,7 +1,6 @@ package org.hso.ecommerce.controller.shop; import org.hso.ecommerce.action.shop.CreateOrderAction; -import org.hso.ecommerce.action.shop.EnableTrackingAction; import org.hso.ecommerce.entities.booking.BookingAccountEntry; import org.hso.ecommerce.entities.booking.PaymentMethod; import org.hso.ecommerce.entities.shop.Address; @@ -11,7 +10,7 @@ import org.hso.ecommerce.entities.user.User; import org.hso.ecommerce.repos.booking.BookingAccountEntryRepository; import org.hso.ecommerce.repos.booking.BookingRepository; import org.hso.ecommerce.repos.shop.ArticleRepository; -import org.hso.ecommerce.repos.shop.CustomerOderRepository; +import org.hso.ecommerce.repos.shop.CustomerOrderRepository; import org.hso.ecommerce.repos.user.UserRepository; import org.hso.ecommerce.repos.warehouse.WarehouseBookingPositionSlotEntryRepository; import org.hso.ecommerce.repos.warehouse.WarehouseBookingRepository; @@ -45,7 +44,7 @@ public class ShopCheckoutController { private final WarehouseBookingRepository warehouseBookingRepository = null; @Autowired - private final CustomerOderRepository customerOderRepository = null; + private final CustomerOrderRepository customerOderRepository = null; @Autowired private final WarehouseBookingPositionSlotEntryRepository wbeseRepo = null; @@ -122,7 +121,7 @@ public class ShopCheckoutController { user, expectedPrice, Address.fromString(address), - PaymentMethod.fromCreditCarNumber(cardnumber), + PaymentMethod.fromCreditCardNumber(cardnumber), bookingEntryRepository.getByUser(user.id).orElse(BookingAccountEntry.newUser(user)), bookingEntryRepository.getByVat().orElse(BookingAccountEntry.newVat()), bookingEntryRepository.getByMain().orElse(BookingAccountEntry.newMain()) @@ -136,7 +135,6 @@ public class ShopCheckoutController { CreateOrderAction.Result result = null; try { result = action.finish(); - //EnableTrackingAction.addTrackingInfo(result.customerOrder); customerOderRepository.save(result.customerOrder); bookingRepository.saveAll(result.bookings); diff --git a/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopSearchController.java b/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopSearchController.java index 1d14c61..47b8acf 100644 --- a/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopSearchController.java +++ b/prototype/src/main/java/org/hso/ecommerce/controller/shop/ShopSearchController.java @@ -1,5 +1,6 @@ package org.hso.ecommerce.controller.shop; +import org.hso.ecommerce.action.shop.SearchByTermAction; import org.hso.ecommerce.entities.shop.Article; import org.hso.ecommerce.repos.shop.ArticleRepository; import org.hso.ecommerce.repos.shop.CategoryRepository; @@ -32,7 +33,8 @@ public class ShopSearchController { model.addAttribute("categories", categoryRepository.getCategories()); //for sidebar if (term != null) { //if search by Term - List
articles = articleRepository.getArticlesByTerm(term); //search by Term + term = term.trim(); + List
articles = SearchByTermAction.searchByTerm(term, articleRepository); model.addAttribute("articles", articles); } else if (category != null) { //if search by Category List
articles = articleRepository.getArticlesByCategory(category); //search by Category diff --git a/prototype/src/main/java/org/hso/ecommerce/entities/booking/Booking.java b/prototype/src/main/java/org/hso/ecommerce/entities/booking/Booking.java index e61ea07..64ef1cd 100644 --- a/prototype/src/main/java/org/hso/ecommerce/entities/booking/Booking.java +++ b/prototype/src/main/java/org/hso/ecommerce/entities/booking/Booking.java @@ -1,6 +1,7 @@ package org.hso.ecommerce.entities.booking; import javax.persistence.*; +import javax.validation.constraints.NotNull; @Entity @Table(name = "bookings") @@ -14,6 +15,9 @@ public class Booking { // always >= 0 public int amountCent; + @NotNull + public java.sql.Timestamp created; + @ManyToOne(optional = true, cascade = CascadeType.ALL) public BookingAccountEntry source; diff --git a/prototype/src/main/java/org/hso/ecommerce/entities/booking/BookingReason.java b/prototype/src/main/java/org/hso/ecommerce/entities/booking/BookingReason.java index 3b93517..8d6572f 100644 --- a/prototype/src/main/java/org/hso/ecommerce/entities/booking/BookingReason.java +++ b/prototype/src/main/java/org/hso/ecommerce/entities/booking/BookingReason.java @@ -43,4 +43,9 @@ public class BookingReason { public BookingReason(SupplierOrder supplierOrder) { this.supplierOrder = supplierOrder; } + + public BookingReason(String comment) { + this.isManuel = true; + this.comment = comment; + } } diff --git a/prototype/src/main/java/org/hso/ecommerce/entities/booking/PaymentMethod.java b/prototype/src/main/java/org/hso/ecommerce/entities/booking/PaymentMethod.java index af0a9c0..fa9fe62 100644 --- a/prototype/src/main/java/org/hso/ecommerce/entities/booking/PaymentMethod.java +++ b/prototype/src/main/java/org/hso/ecommerce/entities/booking/PaymentMethod.java @@ -7,7 +7,7 @@ public class PaymentMethod { public String creditCardNumber; - public static PaymentMethod fromCreditCarNumber(String cardnumber) { + public static PaymentMethod fromCreditCardNumber(String cardnumber) { PaymentMethod m = new PaymentMethod(); m.creditCardNumber = cardnumber; diff --git a/prototype/src/main/java/org/hso/ecommerce/entities/shop/Article.java b/prototype/src/main/java/org/hso/ecommerce/entities/shop/Article.java index 355b5f9..d9fe69a 100644 --- a/prototype/src/main/java/org/hso/ecommerce/entities/shop/Article.java +++ b/prototype/src/main/java/org/hso/ecommerce/entities/shop/Article.java @@ -16,7 +16,7 @@ public class Article { @Basic public long id; - @ManyToOne(optional = false) + @OneToOne(optional = false) public ArticleOffer related; public int shopPricePerUnitNetCent; diff --git a/prototype/src/main/java/org/hso/ecommerce/entities/shop/CustomerOrder.java b/prototype/src/main/java/org/hso/ecommerce/entities/shop/CustomerOrder.java index 8c80c58..853b885 100644 --- a/prototype/src/main/java/org/hso/ecommerce/entities/shop/CustomerOrder.java +++ b/prototype/src/main/java/org/hso/ecommerce/entities/shop/CustomerOrder.java @@ -4,6 +4,7 @@ import org.hso.ecommerce.entities.user.User; import javax.persistence.*; import javax.validation.constraints.NotNull; +import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.List; @@ -43,4 +44,21 @@ public class CustomerOrder { public int totalNetCent; public int totalGrossCent; public int totalVatCent; + + public String formatInDeliverySince(){ + return new SimpleDateFormat("dd.MM.yyyy HH:mm").format(inDeliverySince); + } + + public String formatCreated(){ + return new SimpleDateFormat("dd.MM.yyyy HH:mm").format(created); + } + + public String formatDeliveredAt(){ + return new SimpleDateFormat("dd.MM.yyyy HH:mm").format(deliveredAt); + } + + public String getEstimatedArrival() { + //TODO: get estimated arrival from api + return "TODO TODO TODO"; + } } diff --git a/prototype/src/main/java/org/hso/ecommerce/entities/supplier/ArticleOffer.java b/prototype/src/main/java/org/hso/ecommerce/entities/supplier/ArticleOffer.java index 405fb4a..41296ba 100644 --- a/prototype/src/main/java/org/hso/ecommerce/entities/supplier/ArticleOffer.java +++ b/prototype/src/main/java/org/hso/ecommerce/entities/supplier/ArticleOffer.java @@ -28,5 +28,6 @@ public class ArticleOffer { public boolean shouldBeAdvertised; - + @ManyToOne(optional = true) + public Supplier cheapestSupplier; } diff --git a/prototype/src/main/java/org/hso/ecommerce/entities/user/User.java b/prototype/src/main/java/org/hso/ecommerce/entities/user/User.java index 784d89a..e08c2ee 100644 --- a/prototype/src/main/java/org/hso/ecommerce/entities/user/User.java +++ b/prototype/src/main/java/org/hso/ecommerce/entities/user/User.java @@ -24,6 +24,11 @@ public class User { @Column(unique = true) public String email; + @Column(insertable = false, updatable = false) + public String name; + + public String salutation; + public String passwordHash; public boolean isActive; diff --git a/prototype/src/main/java/org/hso/ecommerce/entities/warehouse/WarehouseBookingPositionSlotEntry.java b/prototype/src/main/java/org/hso/ecommerce/entities/warehouse/WarehouseBookingPositionSlotEntry.java index 444b921..15233df 100644 --- a/prototype/src/main/java/org/hso/ecommerce/entities/warehouse/WarehouseBookingPositionSlotEntry.java +++ b/prototype/src/main/java/org/hso/ecommerce/entities/warehouse/WarehouseBookingPositionSlotEntry.java @@ -25,7 +25,12 @@ public class WarehouseBookingPositionSlotEntry { @ManyToOne public Slot slot; - public WarehouseBookingPositionSlotEntry copyAddAmount(int amount) { + public WarehouseBookingPositionSlotEntry copyAddAmount(int amount, Article article) { + // Article can be changed if newSumSlot == 0. + if (this.newSumSlot != 0 && this.article.id != article.id) { + throw new IllegalArgumentException("Article does not match."); + } + WarehouseBookingPositionSlotEntry e = new WarehouseBookingPositionSlotEntry(); e.article = article; @@ -38,4 +43,14 @@ public class WarehouseBookingPositionSlotEntry { return e; } + + public static WarehouseBookingPositionSlotEntry empty(Article article, Slot slot) { + WarehouseBookingPositionSlotEntry e = new WarehouseBookingPositionSlotEntry(); + + e.article = article; + e.slot = slot; + e.newSumSlot = 0; + + return e; + } } diff --git a/prototype/src/main/java/org/hso/ecommerce/repos/booking/BookingRepository.java b/prototype/src/main/java/org/hso/ecommerce/repos/booking/BookingRepository.java index 454b3f3..e72ae6a 100644 --- a/prototype/src/main/java/org/hso/ecommerce/repos/booking/BookingRepository.java +++ b/prototype/src/main/java/org/hso/ecommerce/repos/booking/BookingRepository.java @@ -1,12 +1,28 @@ package org.hso.ecommerce.repos.booking; +import java.util.List; + import org.hso.ecommerce.entities.booking.Booking; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; import org.springframework.stereotype.Repository; @Repository public interface BookingRepository extends JpaRepository { + @Query("SELECT b FROM Booking b ORDER BY b.id DESC") + List allBookingsReverseChronologically(); + + @Query("SELECT b FROM Booking b LEFT JOIN b.source s LEFT JOIN b.destination d WHERE s.isMainAccount = 1 OR d.isMainAccount = 1 ORDER BY b.id DESC") + List mainBookingsReverseChronologically(); + + @Query("SELECT b FROM Booking b LEFT JOIN b.source s LEFT JOIN b.destination d WHERE s.isVATAccount = 1 OR d.isVATAccount = 1 ORDER BY b.id DESC") + List vatBookingsReverseChronologically(); + + @Query("SELECT b FROM Booking b LEFT JOIN b.source s LEFT JOIN b.destination d WHERE s.userAccount.id = :customerId OR d.userAccount.id = :customerId ORDER BY b.id DESC") + List customerBookingsReverseChronologically(long customerId); + + @Query("SELECT b FROM Booking b LEFT JOIN b.source s LEFT JOIN b.destination d WHERE s.supplierAccount.id = :supplierId OR d.supplierAccount.id = :supplierId ORDER BY b.id DESC") + List supplierBookingsReverseChronologically(long supplierId); + } - - diff --git a/prototype/src/main/java/org/hso/ecommerce/repos/shop/ArticleRepository.java b/prototype/src/main/java/org/hso/ecommerce/repos/shop/ArticleRepository.java index 0340f59..0925ea0 100644 --- a/prototype/src/main/java/org/hso/ecommerce/repos/shop/ArticleRepository.java +++ b/prototype/src/main/java/org/hso/ecommerce/repos/shop/ArticleRepository.java @@ -1,6 +1,7 @@ package org.hso.ecommerce.repos.shop; import org.hso.ecommerce.entities.shop.Article; +import org.hso.ecommerce.entities.supplier.ArticleOffer; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; @@ -12,26 +13,40 @@ import java.util.Optional; @Repository public interface ArticleRepository extends JpaRepository { - @Query("SELECT a FROM Article a WHERE a.id = :articleId") - Article findArticleById(@Param("articleId") long articleId); + /*** + * use findById instead. + */ + @Deprecated + @Query("SELECT a FROM Article a WHERE a.id = :articleId") + Article findArticleById(@Param("articleId") long articleId); - @Query("SELECT a FROM Article a") - List
findAll(); + @Query("SELECT a FROM Article a") + List
findAll(); @Query(value = "Select a.* from articles as a, article_offers as ao, warehouse_booking_position_entries as wbpe where a.related_id = ao.id and wbpe.article_id = a.id and ao.should_be_advertised = true group by wbpe.slot_id having max(wbpe.id) and wbpe.new_sum_slot != 0", nativeQuery = true) List
getAdvertisedArticles(); - @Query("SELECT a FROM CustomerOrderPosition cop JOIN cop.order co JOIN co.customer c JOIN cop.article a ORDER BY co.id DESC") - List
getOrderedArticles(); + @Query("SELECT a FROM CustomerOrderPosition cop JOIN cop.order co JOIN co.customer c JOIN cop.article a ORDER BY co.id DESC") + List
getOrderedArticles(); @Query("SELECT a FROM CustomerOrderPosition cop JOIN cop.order co JOIN co.customer c JOIN cop.article a WHERE c.id = :customerId ORDER BY co.id DESC") List
getOrderedArticles(long customerId); + /*** + * use type safe findArticleByArticleOffer instead. + */ + @Deprecated @Query(value = "SELECT a.id FROM articles a WHERE a.related_id = :relatedId", nativeQuery = true) Optional findArticleIDByRelatedID(@Param("relatedId") long relatedId); - + + @Query(value = "SELECT a FROM Article a Where a.related = :related") + Optional
findArticleByArticleOffer(ArticleOffer related); + @Query(value = "Select a.* from articles as a, warehouse_booking_position_entries as wbpe where wbpe.article_id = a.id and a.title LIKE %:term% group by wbpe.slot_id having max(wbpe.id) and wbpe.new_sum_slot != 0", nativeQuery = true) - List
getArticlesByTerm(String term); + List
getArticlesByTermInTitle(String term); + + @Query(value = "Select a.* from articles as a, warehouse_booking_position_entries as wbpe where wbpe.article_id = a.id and a.description LIKE %:term% group by wbpe.slot_id having max(wbpe.id) and wbpe.new_sum_slot != 0", nativeQuery = true) + List
getArticlesByTermInDescription(String term); @Query(value = "Select a.* from articles as a, categories as c, article_categories_bindings as acb, warehouse_booking_position_entries as wbpe where wbpe.article_id = a.id and acb.articles_id = a.id and acb.categories_id = c.id and c.name = :category group by wbpe.slot_id having max(wbpe.id) and wbpe.new_sum_slot != 0", nativeQuery = true) List
getArticlesByCategory(String category); diff --git a/prototype/src/main/java/org/hso/ecommerce/repos/shop/CustomerOderRepository.java b/prototype/src/main/java/org/hso/ecommerce/repos/shop/CustomerOrderRepository.java similarity index 80% rename from prototype/src/main/java/org/hso/ecommerce/repos/shop/CustomerOderRepository.java rename to prototype/src/main/java/org/hso/ecommerce/repos/shop/CustomerOrderRepository.java index 6f673d4..653cd08 100644 --- a/prototype/src/main/java/org/hso/ecommerce/repos/shop/CustomerOderRepository.java +++ b/prototype/src/main/java/org/hso/ecommerce/repos/shop/CustomerOrderRepository.java @@ -9,8 +9,10 @@ import org.springframework.transaction.annotation.Transactional; import java.util.List; +import java.util.List; + @Repository -public interface CustomerOderRepository extends JpaRepository { +public interface CustomerOrderRepository extends JpaRepository { @Query("SELECT SUM(cop.quantity) FROM CustomerOrderPosition cop JOIN cop.order co WHERE cop.article.id = :articleId AND co.created >= :begin AND co.created < :end") Integer countOrdersOfArticleInTimespan( @@ -24,5 +26,9 @@ public interface CustomerOderRepository extends JpaRepository getOrdersByUserId(long userId); + +} \ No newline at end of file diff --git a/prototype/src/main/java/org/hso/ecommerce/repos/supplier/SupplierOrderRepository.java b/prototype/src/main/java/org/hso/ecommerce/repos/supplier/SupplierOrderRepository.java index 9d15e02..06ad249 100644 --- a/prototype/src/main/java/org/hso/ecommerce/repos/supplier/SupplierOrderRepository.java +++ b/prototype/src/main/java/org/hso/ecommerce/repos/supplier/SupplierOrderRepository.java @@ -1,8 +1,11 @@ package org.hso.ecommerce.repos.supplier; +import java.util.List; + import org.hso.ecommerce.entities.supplier.SupplierOrder; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; @Repository @@ -11,4 +14,9 @@ public interface SupplierOrderRepository extends JpaRepository findOrderBySupplierID(@Param("supplierId") long supplierId); + + @Query("SELECT a FROM SupplierOrder a") + List findAll(); } diff --git a/prototype/src/main/java/org/hso/ecommerce/repos/supplier/SupplierRepository.java b/prototype/src/main/java/org/hso/ecommerce/repos/supplier/SupplierRepository.java index 2b81659..14b3a75 100644 --- a/prototype/src/main/java/org/hso/ecommerce/repos/supplier/SupplierRepository.java +++ b/prototype/src/main/java/org/hso/ecommerce/repos/supplier/SupplierRepository.java @@ -1,10 +1,19 @@ package org.hso.ecommerce.repos.supplier; +import java.util.List; + import org.hso.ecommerce.entities.supplier.Supplier; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; @Repository public interface SupplierRepository extends JpaRepository { - -} + + @Query("SELECT a FROM Supplier a") + List findAll(); + + @Query("SELECT a FROM Supplier a WHERE a.id = :supplierId") + Supplier findSupplierById(@Param("supplierId") long supplierId); +} \ No newline at end of file diff --git a/prototype/src/main/java/org/hso/ecommerce/repos/warehouse/WarehouseBookingPositionSlotEntryRepository.java b/prototype/src/main/java/org/hso/ecommerce/repos/warehouse/WarehouseBookingPositionSlotEntryRepository.java index cb9902e..804e8b7 100644 --- a/prototype/src/main/java/org/hso/ecommerce/repos/warehouse/WarehouseBookingPositionSlotEntryRepository.java +++ b/prototype/src/main/java/org/hso/ecommerce/repos/warehouse/WarehouseBookingPositionSlotEntryRepository.java @@ -13,10 +13,12 @@ public interface WarehouseBookingPositionSlotEntryRepository extends JpaReposito @Query(value = "Select e.id, e.article_id, e.new_sum_slot, e.slot_id from warehouse_booking_position_entries as e, warehouse_slots as s where e.slot_id = s.id AND e.article_id = :article GROUP BY s.slot_num HAVING max(e.id)", nativeQuery = true) List getByArticle(long article); - - + @Query(value = "SELECT SUM(w.new_sum_slot) FROM warehouse_booking_position_entries as w WHERE w.article_id = :articleid", nativeQuery = true) Optional getArticleStock(long articleid); - + + @Query(value = "Select e.id, e.article_id, e.new_sum_slot, e.slot_id from warehouse_booking_position_entries as e, warehouse_slots as s where e.slot_id = s.id AND s.slot_num = :slotnum GROUP BY s.slot_num HAVING max(e.id)", nativeQuery = true) + Optional getBySlotNum(long slotnum); + } diff --git a/prototype/src/main/java/org/hso/ecommerce/repos/warehouse/WarehouseBookingRepository.java b/prototype/src/main/java/org/hso/ecommerce/repos/warehouse/WarehouseBookingRepository.java index 8d01092..08434c4 100644 --- a/prototype/src/main/java/org/hso/ecommerce/repos/warehouse/WarehouseBookingRepository.java +++ b/prototype/src/main/java/org/hso/ecommerce/repos/warehouse/WarehouseBookingRepository.java @@ -2,10 +2,16 @@ package org.hso.ecommerce.repos.warehouse; import org.hso.ecommerce.entities.warehouse.WarehouseBooking; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; import org.springframework.stereotype.Repository; +import java.util.List; + @Repository public interface WarehouseBookingRepository extends JpaRepository { + @Query("Select b FROM WarehouseBooking b WHERE b.isDone = 0") + List findNotDone(); + } diff --git a/prototype/src/main/resources/static/js/editViewUpdateTax.js b/prototype/src/main/resources/static/js/editViewUpdateTax.js new file mode 100644 index 0000000..0724150 --- /dev/null +++ b/prototype/src/main/resources/static/js/editViewUpdateTax.js @@ -0,0 +1,15 @@ +document.addEventListener("DOMContentLoaded", function() { + let priceElm = document.getElementById("price"); + let priceGrossElm = document.getElementById("priceGross"); + let vatPercent = parseInt(document.getElementById("vatPercent").value); + + let updateFn = () => { + let net = Math.floor(priceElm.value*100); + let vat = Math.floor((net * vatPercent) / 100); + let gross = net + vat; + + priceGrossElm.innerText = (gross / 100.0).toFixed(2).replace("\\.", ","); + }; + + priceElm.onchange = updateFn; +}); diff --git a/prototype/src/main/resources/templates/fragments/customer.html b/prototype/src/main/resources/templates/fragments/customer.html index d47a06a..f8ba1ff 100644 --- a/prototype/src/main/resources/templates/fragments/customer.html +++ b/prototype/src/main/resources/templates/fragments/customer.html @@ -12,8 +12,6 @@ diff --git a/prototype/src/main/resources/templates/fragments/header.html b/prototype/src/main/resources/templates/fragments/header.html index 054c332..349f72c 100644 --- a/prototype/src/main/resources/templates/fragments/header.html +++ b/prototype/src/main/resources/templates/fragments/header.html @@ -18,7 +18,6 @@ diff --git a/prototype/src/main/resources/templates/intern/accounting/index.html b/prototype/src/main/resources/templates/intern/accounting/index.html index 206e218..7d832fa 100644 --- a/prototype/src/main/resources/templates/intern/accounting/index.html +++ b/prototype/src/main/resources/templates/intern/accounting/index.html @@ -49,48 +49,21 @@ Referenz - - 10.09.2019 14:10 - 119,00 EUR - - - - - Kunde 5080 - 0 EUR - Kunden-Bezahlung - Bezahlung mit Kreditkarte XXXXX480 - + + + - - 10.09.2019 13:45 - 19,00 EUR - Hauptkonto - 331,00 EUR - Mehrwertsteuer - 1510,95 EUR - Kunden-Bestellung - 2504 - + + + - - 10.09.2019 13:45 - 100,00 EUR - Kunde 5080 - -100,00 EUR - Hauptkonto - 350,00 EUR - Kunden-Bestellung - 2504 - + + + - - 19.08.2019 12:31 - 250,00 EUR - - - - - Hauptkonto - 250,00 EUR - Startkapital - - + + + diff --git a/prototype/src/main/resources/templates/intern/accounting/main.html b/prototype/src/main/resources/templates/intern/accounting/main.html index 7532df5..ed7345c 100644 --- a/prototype/src/main/resources/templates/intern/accounting/main.html +++ b/prototype/src/main/resources/templates/intern/accounting/main.html @@ -25,7 +25,7 @@

Kontostand

-

331,00 EUR

+

@@ -42,33 +42,18 @@ - - - + + - + + - - + - - - - - - - - - - - - - - - + +
Grund Referenz
10.09.2019 13:45-19,00 EUR
+ - Mehrwertsteuer331,00 EUR - Kunden-Bestellung2504
-
10.09.2019 13:45100,00 EURKunde 5080350,00 EURKunden-Bestellung2504
19.08.2019 12:31250,00 EUR -250,00 EURStartkapital - +
diff --git a/prototype/src/main/resources/templates/intern/accounting/vat.html b/prototype/src/main/resources/templates/intern/accounting/vat.html index 1f43097..806141c 100644 --- a/prototype/src/main/resources/templates/intern/accounting/vat.html +++ b/prototype/src/main/resources/templates/intern/accounting/vat.html @@ -26,7 +26,7 @@

Kontostand

-

1510.95 EUR

+

@@ -43,13 +43,18 @@ - - - - - - - + + + +
Grund Referenz
10.09.2019 13:4519,00 EURHauptkonto1510,95 EURKunden-Bestellung2504
+ + + + + + + +
diff --git a/prototype/src/main/resources/templates/intern/customerOrders/id.html b/prototype/src/main/resources/templates/intern/customerOrders/id.html index 2ea505f..b718b7e 100644 --- a/prototype/src/main/resources/templates/intern/customerOrders/id.html +++ b/prototype/src/main/resources/templates/intern/customerOrders/id.html @@ -63,7 +63,6 @@
- diff --git a/prototype/src/main/resources/templates/intern/customers/id.html b/prototype/src/main/resources/templates/intern/customers/id.html index 33ba95b..30962fc 100644 --- a/prototype/src/main/resources/templates/intern/customers/id.html +++ b/prototype/src/main/resources/templates/intern/customers/id.html @@ -23,7 +23,7 @@

+ + +
+ + \ No newline at end of file diff --git a/prototype/src/main/resources/templates/user/bonuspoints.html b/prototype/src/main/resources/templates/user/bonuspoints.html deleted file mode 100644 index e7d1dc8..0000000 --- a/prototype/src/main/resources/templates/user/bonuspoints.html +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - Bonusprogramm - - - - - - - -
- -
-
-
-

Ihr Bonuspunktestand beträgt:

-

15

-
-
-

Bonuspunkte sichern

-

- Sie sichern sich automatisch bei jedem Einkaufen pro Angefangenen - 10 EUR einen Bonuspunkt. -

-

- Eine Übersicht ihrer Bonuspunkt finden sie hier auf dieser - Bonus. -

-

- Um die Bonuspunkte einzulösen hacken sie einfach - "Bonuspunkte" verwenden beim Abschließen der Bestellung - an. Für jeden Bonuspunkt wird ihnen 0,50 EUR gutgeschrieben. -

-
-
- -
-
-
-
-
-
-
-
- - - diff --git a/prototype/src/main/resources/templates/user/notifications/index.html b/prototype/src/main/resources/templates/user/notifications/index.html deleted file mode 100644 index 5cc4de5..0000000 --- a/prototype/src/main/resources/templates/user/notifications/index.html +++ /dev/null @@ -1,92 +0,0 @@ - - - - - - - - Meine Benachrichtigungen - - - - - - - -
- -
-
-
-

Nachricht vom 17.08.2020, 14:38 Uhr

-

Ihre Bestellung kommt voraussichtlich am Donnerstag, den 20.08.2020

-

- Vielen Dank für Ihre Bestellung der folgenden Artikel:
-
- 2x tolle Kamera
- 1x Bluetooth Kopfhörer
- 3x USB-Magic Light
-
- Die Sendung wird Ihnen voraussichtlich am Donnerstag, den 20.08.2020 zugestellt. - Den aktuellen Status des Pakets können Sie jederzeit in der Bestellübersicht - nachvollziehen. -

- -
-
-

Nachricht vom 15.08.2020, 16:38 Uhr

-

Jetzt unsere Tagesangebote entdecken.

-

- Entdecken sie jetzt unseren neusten Angebote: -

- -
-
-

Nachricht vom 13.08.2020, 14:38 Uhr

-

Ihre Bestellung ist angekommen.

-

- Vielen Dank für Ihre Bestellung der folgenden Artikel:
-
- 3x USB-Magic Light
-
- Ihre Bestellungen ist angekommen. -

-
-
-
-
-
-
-
- - - diff --git a/prototype/src/main/resources/templates/user/orders/index.html b/prototype/src/main/resources/templates/user/orders/index.html index a60e623..023910d 100644 --- a/prototype/src/main/resources/templates/user/orders/index.html +++ b/prototype/src/main/resources/templates/user/orders/index.html @@ -21,30 +21,22 @@
-
-

Bestellung vom 27.01.2020

+
+

- + + - + - - - - - +
LieferstatusUnterwegs
Vorraussichtliche Ankunft: 29.01.2020
Unterwegs
Vorraussichtliche Ankunft:
Angekommen
Ankunft:
SendeverfolgungsnummerXE51451436DE
- Hans Maier
- Hauptstraße 12
- 74880 Musterstadt
- Deutschland
-
Eingelösste Bonuspunkte10
@@ -55,17 +47,11 @@ Menge Preis (Brutto) - - - Kamera - 1 - 100,50 EUR - - - - Earbuds - 3 - 63,95 EUR + + + + + @@ -77,19 +63,13 @@ Artikel (Netto) - 120,00 EUR + - Bonuspunkte - 5,00 EUR - - - - - Umsatzsteuer (19%) - 42,00 EUR + Umsatzsteuer + @@ -98,89 +78,7 @@

Gesammtpreis

-

240,79 EUR

- - - -
-
-

Bestellung vom 01.01.2020

-
- - - - - - - - - - - - - - - - - -
LieferstatusAngekommen
03.01.2020
SendeverfolgungsnummerXE5140684351DE
- Hans Maier
- Hauptstraße 12
- 74880 Musterstadt
- Deutschland
-
Gutgeschriebene Bonuspunkte5
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
BildNameMengePreis pro Artikel (Brutto)
Billige Kamera 140,50 EUR
Apfel 51,00 EUR
PositionPreis
Artikel (Netto) 20,00 EUR
Umsatzsteuer (19%) 5,00 EUR
Umsatzsteuer (7%) 2,00 EUR
-

Gesammtpreis

-
-

50,79 EUR

+

diff --git a/prototype/src/main/resources/templates/user/settings.html b/prototype/src/main/resources/templates/user/settings.html index 29f6ec4..80bd60e 100644 --- a/prototype/src/main/resources/templates/user/settings.html +++ b/prototype/src/main/resources/templates/user/settings.html @@ -21,19 +21,19 @@
-
+

Login Daten

- +
-
+

Sicherheit

@@ -42,8 +42,8 @@ - - + + @@ -51,7 +51,7 @@
-
+

Rechungs- und Lieferinformation

@@ -59,7 +59,7 @@
-
-
- +