Implement CreateCustomerOrderAction; Not implemented: correct booking and WarehouseBooking fetching...
Puhh, that was a struggle to get working. Damn JPA Shit
This commit is contained in:
		@ -1,9 +1,9 @@
 | 
			
		||||
/* password is 123 */
 | 
			
		||||
INSERT INTO users ("created", "email", "password_hash", "gets_ads", "is_active", "is_employee", "isb2b")
 | 
			
		||||
VALUES (datetime('now','localtime') ||'.0', "emp@ecom", "$2a$10$zFiqcePBmXHErD86vkI.vO1dnX20ezoVSM8xjGi59nktXYQv0o.fK", "0", "1", "1", "0");
 | 
			
		||||
INSERT INTO users ("created", "email", "password_hash", "is_active", "is_employee")
 | 
			
		||||
VALUES (datetime('now','localtime') ||'.0', "emp@ecom", "$2a$10$zFiqcePBmXHErD86vkI.vO1dnX20ezoVSM8xjGi59nktXYQv0o.fK", "1", "1");
 | 
			
		||||
 | 
			
		||||
INSERT INTO users ("created", "email", "password_hash", "gets_ads", "is_active", "is_employee", "isb2b")
 | 
			
		||||
VALUES (datetime('now','localtime') ||'.0', "user@ecom", "$2a$10$zFiqcePBmXHErD86vkI.vO1dnX20ezoVSM8xjGi59nktXYQv0o.fK", "1", "1", "0", "0");
 | 
			
		||||
INSERT INTO users ("created", "email", "password_hash", "is_active", "is_employee")
 | 
			
		||||
VALUES (datetime('now','localtime') ||'.0', "user@ecom", "$2a$10$zFiqcePBmXHErD86vkI.vO1dnX20ezoVSM8xjGi59nktXYQv0o.fK", "1", "0");
 | 
			
		||||
 | 
			
		||||
INSERT INTO users ("created", "email", "password_hash", "gets_ads", "is_active", "is_employee", "isb2b")
 | 
			
		||||
VALUES (datetime('now','localtime') ||'.0', "blocked@ecom", "$2a$10$zFiqcePBmXHErD86vkI.vO1dnX20ezoVSM8xjGi59nktXYQv0o.fK", "1", "0", "0", "0");
 | 
			
		||||
INSERT INTO users ("created", "email", "password_hash", "is_active", "is_employee")
 | 
			
		||||
VALUES (datetime('now','localtime') ||'.0', "blocked@ecom", "$2a$10$zFiqcePBmXHErD86vkI.vO1dnX20ezoVSM8xjGi59nktXYQv0o.fK", "0", "0");
 | 
			
		||||
@ -0,0 +1,30 @@
 | 
			
		||||
package org.hso.ecommerce.action.booking;
 | 
			
		||||
 | 
			
		||||
import org.hso.ecommerce.entities.booking.Booking;
 | 
			
		||||
import org.hso.ecommerce.entities.booking.BookingAccountEntry;
 | 
			
		||||
import org.hso.ecommerce.entities.booking.BookingReason;
 | 
			
		||||
 | 
			
		||||
public class CreateBookingAction {
 | 
			
		||||
 | 
			
		||||
    private Booking booking;
 | 
			
		||||
 | 
			
		||||
    public CreateBookingAction(BookingAccountEntry source, BookingAccountEntry destination, BookingReason reason, int amountCent) {
 | 
			
		||||
        booking = new Booking();
 | 
			
		||||
        booking.reason = reason;
 | 
			
		||||
        booking.amountCent = amountCent;
 | 
			
		||||
 | 
			
		||||
        assert source != null || destination != null;
 | 
			
		||||
 | 
			
		||||
        if (source != null) {
 | 
			
		||||
            booking.source = source.copyAddAmount(-amountCent);
 | 
			
		||||
        }
 | 
			
		||||
        if (destination != null) {
 | 
			
		||||
            booking.destination = destination.copyAddAmount(amountCent);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public Booking finish() {
 | 
			
		||||
        return booking;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,177 @@
 | 
			
		||||
package org.hso.ecommerce.action.shop;
 | 
			
		||||
 | 
			
		||||
import org.hso.ecommerce.action.booking.CreateBookingAction;
 | 
			
		||||
import org.hso.ecommerce.entities.booking.*;
 | 
			
		||||
import org.hso.ecommerce.entities.shop.Address;
 | 
			
		||||
import org.hso.ecommerce.entities.shop.Article;
 | 
			
		||||
import org.hso.ecommerce.entities.shop.CustomerOrder;
 | 
			
		||||
import org.hso.ecommerce.entities.shop.CustomerOrderPosition;
 | 
			
		||||
import org.hso.ecommerce.entities.user.User;
 | 
			
		||||
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 CreateOrderAction {
 | 
			
		||||
 | 
			
		||||
    private User user;
 | 
			
		||||
    Address destination;
 | 
			
		||||
 | 
			
		||||
    private int expectedTotalGrossCent;
 | 
			
		||||
 | 
			
		||||
    private int totalNetCent;
 | 
			
		||||
    private int totalVatCent;
 | 
			
		||||
    private PaymentMethod method;
 | 
			
		||||
 | 
			
		||||
    private BookingAccountEntry latestUserBooking;
 | 
			
		||||
    private BookingAccountEntry latestVatBooking;
 | 
			
		||||
    private BookingAccountEntry latestMainBooking;
 | 
			
		||||
 | 
			
		||||
    private List<OrderItem> orderItems = new ArrayList<>();
 | 
			
		||||
 | 
			
		||||
    public CreateOrderAction(
 | 
			
		||||
            User user,
 | 
			
		||||
            int expectedTotalGrossCent,
 | 
			
		||||
            Address destination,
 | 
			
		||||
            PaymentMethod method,
 | 
			
		||||
            BookingAccountEntry latestUserBooking,
 | 
			
		||||
            BookingAccountEntry latestVatBooking,
 | 
			
		||||
            BookingAccountEntry latestMainBooking
 | 
			
		||||
    ) {
 | 
			
		||||
        this.user = user;
 | 
			
		||||
        this.expectedTotalGrossCent = expectedTotalGrossCent;
 | 
			
		||||
        this.destination = destination;
 | 
			
		||||
        this.method = method;
 | 
			
		||||
 | 
			
		||||
        this.latestUserBooking = latestUserBooking;
 | 
			
		||||
        assert latestUserBooking.userAccount.id == user.id;
 | 
			
		||||
 | 
			
		||||
        this.latestVatBooking = latestVatBooking;
 | 
			
		||||
        assert latestVatBooking.isVATAccount;
 | 
			
		||||
 | 
			
		||||
        this.latestMainBooking = latestMainBooking;
 | 
			
		||||
        assert latestMainBooking.isMainAccount;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void addArticle(Article article, int quantity, List<WarehouseBookingPositionSlotEntry> availableSlots) {
 | 
			
		||||
        for (WarehouseBookingPositionSlotEntry slot : availableSlots) {
 | 
			
		||||
            assert slot.article.id == article.id;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        orderItems.add(new OrderItem(article, availableSlots, quantity));
 | 
			
		||||
 | 
			
		||||
        totalNetCent += article.shopPricePerUnitNetCent * quantity;
 | 
			
		||||
        totalVatCent += article.getVat() * quantity;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public Result finish() {
 | 
			
		||||
        CustomerOrder order = createOrder();
 | 
			
		||||
        CustomerPayment payment = createPayment();
 | 
			
		||||
 | 
			
		||||
        List<Booking> 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());
 | 
			
		||||
 | 
			
		||||
        WarehouseBooking warehouseBooking = createWarehouseBooking(order);
 | 
			
		||||
 | 
			
		||||
        return new Result(
 | 
			
		||||
                order,
 | 
			
		||||
                warehouseBooking,
 | 
			
		||||
                bookingList
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private WarehouseBooking createWarehouseBooking(CustomerOrder order) {
 | 
			
		||||
        WarehouseBooking booking = new WarehouseBooking();
 | 
			
		||||
        booking.created = new Timestamp(new Date().getTime());
 | 
			
		||||
        booking.reason = new BookingReason(order);
 | 
			
		||||
 | 
			
		||||
        for (OrderItem item : orderItems) {
 | 
			
		||||
            int needed = item.quantity;
 | 
			
		||||
 | 
			
		||||
            for (WarehouseBookingPositionSlotEntry slot : item.availableSlots) {
 | 
			
		||||
                int remove = Math.min(slot.newSumSlot, needed);
 | 
			
		||||
                needed -= remove;
 | 
			
		||||
 | 
			
		||||
                WarehouseBookingPosition bookingPosition = new WarehouseBookingPosition();
 | 
			
		||||
 | 
			
		||||
                bookingPosition.article = item.article;
 | 
			
		||||
                bookingPosition.amount = -remove;
 | 
			
		||||
                bookingPosition.slotEntry = slot.copyAddAmount(-remove);
 | 
			
		||||
                bookingPosition.booking = booking;
 | 
			
		||||
 | 
			
		||||
                booking.positions.add(bookingPosition);
 | 
			
		||||
 | 
			
		||||
                if (needed == 0) {
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return booking;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private CustomerPayment createPayment() {
 | 
			
		||||
        CustomerPayment payment = new CustomerPayment();
 | 
			
		||||
        payment.amountCent = totalNetCent + totalVatCent;
 | 
			
		||||
        payment.payment = method;
 | 
			
		||||
        return payment;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    private CustomerOrder createOrder() {
 | 
			
		||||
        assert totalNetCent + totalVatCent == expectedTotalGrossCent;
 | 
			
		||||
 | 
			
		||||
        CustomerOrder customerOrder = new CustomerOrder();
 | 
			
		||||
        customerOrder.customer = user;
 | 
			
		||||
        customerOrder.destination = destination;
 | 
			
		||||
 | 
			
		||||
        for (OrderItem item : orderItems) {
 | 
			
		||||
            CustomerOrderPosition position = new CustomerOrderPosition();
 | 
			
		||||
            position.article = item.article;
 | 
			
		||||
            position.pricePerUnit = item.article.shopPricePerUnitNetCent;
 | 
			
		||||
            position.quantity = item.quantity;
 | 
			
		||||
 | 
			
		||||
            position.order = customerOrder;
 | 
			
		||||
 | 
			
		||||
            customerOrder.positions.add(position);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        customerOrder.created = new Timestamp(new Date().getTime());
 | 
			
		||||
 | 
			
		||||
        customerOrder.totalNetCent = totalNetCent;
 | 
			
		||||
        customerOrder.totalVatCent = totalVatCent;
 | 
			
		||||
        customerOrder.totalGrossCent = totalNetCent + totalVatCent;
 | 
			
		||||
 | 
			
		||||
        return customerOrder;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static class Result {
 | 
			
		||||
        public final CustomerOrder customerOrder;
 | 
			
		||||
        public final WarehouseBooking warehouseBooking;
 | 
			
		||||
        public final List<Booking> bookings;
 | 
			
		||||
 | 
			
		||||
        Result(CustomerOrder customerOrder, WarehouseBooking warehouseBooking, List<Booking> bookings) {
 | 
			
		||||
            this.customerOrder = customerOrder;
 | 
			
		||||
            this.warehouseBooking = warehouseBooking;
 | 
			
		||||
            this.bookings = bookings;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static class OrderItem {
 | 
			
		||||
        List<WarehouseBookingPositionSlotEntry> availableSlots;
 | 
			
		||||
        int quantity;
 | 
			
		||||
        Article article;
 | 
			
		||||
 | 
			
		||||
        public OrderItem(Article article, List<WarehouseBookingPositionSlotEntry> availableSlots, int quantity) {
 | 
			
		||||
            this.article = article;
 | 
			
		||||
            this.availableSlots = availableSlots;
 | 
			
		||||
            this.quantity = quantity;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,11 @@
 | 
			
		||||
package org.hso.ecommerce.action.shop;
 | 
			
		||||
 | 
			
		||||
import org.hso.ecommerce.entities.shop.CustomerOrder;
 | 
			
		||||
 | 
			
		||||
public class EnableTrackingAction {
 | 
			
		||||
 | 
			
		||||
    public static void addTrackingInfo(CustomerOrder customerOrder) {
 | 
			
		||||
        // TODO:
 | 
			
		||||
        customerOrder.trackingId = "555-NASE";
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -1,7 +0,0 @@
 | 
			
		||||
package org.hso.ecommerce.action.somepackage;
 | 
			
		||||
 | 
			
		||||
public class DemoAction {
 | 
			
		||||
    // TODO: remove me.
 | 
			
		||||
    // mksubpackage
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -1,14 +1,23 @@
 | 
			
		||||
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;
 | 
			
		||||
import org.hso.ecommerce.entities.shop.Article;
 | 
			
		||||
import org.hso.ecommerce.entities.shop.ShoppingCart;
 | 
			
		||||
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.user.UserRepository;
 | 
			
		||||
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.web.bind.annotation.GetMapping;
 | 
			
		||||
import org.springframework.web.bind.annotation.PostMapping;
 | 
			
		||||
import org.springframework.web.bind.annotation.RequestAttribute;
 | 
			
		||||
import org.springframework.web.bind.annotation.RequestMapping;
 | 
			
		||||
import org.springframework.web.bind.annotation.*;
 | 
			
		||||
 | 
			
		||||
import javax.servlet.http.HttpServletRequest;
 | 
			
		||||
import javax.servlet.http.HttpSession;
 | 
			
		||||
@ -19,9 +28,27 @@ import java.util.TreeMap;
 | 
			
		||||
@RequestMapping("/shop/")
 | 
			
		||||
public class ShopCheckoutController {
 | 
			
		||||
 | 
			
		||||
    @Autowired
 | 
			
		||||
    private final UserRepository userRepository = null;
 | 
			
		||||
 | 
			
		||||
    @Autowired
 | 
			
		||||
    private final ArticleRepository articleRepository = null;
 | 
			
		||||
 | 
			
		||||
    @Autowired
 | 
			
		||||
    private final BookingAccountEntryRepository bookingEntryRepository = null;
 | 
			
		||||
 | 
			
		||||
    @Autowired
 | 
			
		||||
    private final BookingRepository bookingRepository = null;
 | 
			
		||||
 | 
			
		||||
    @Autowired
 | 
			
		||||
    private final WarehouseBookingRepository warehouseBookingRepository = null;
 | 
			
		||||
 | 
			
		||||
    @Autowired
 | 
			
		||||
    private final CustomerOderRepository customerOderRepository = null;
 | 
			
		||||
 | 
			
		||||
    @Autowired
 | 
			
		||||
    private final WarehouseBookingPositionSlotEntryRepository wbeseRepo = null;
 | 
			
		||||
 | 
			
		||||
    @GetMapping("/checkout")
 | 
			
		||||
    public String shopCheckout(HttpSession session,
 | 
			
		||||
                               HttpServletRequest request,
 | 
			
		||||
@ -69,7 +96,43 @@ public class ShopCheckoutController {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @PostMapping("/checkoutFinish")
 | 
			
		||||
    public String shopCheckoutFinish() {
 | 
			
		||||
    public String shopCheckoutFinish(
 | 
			
		||||
            @RequestAttribute(value = "user") User user,
 | 
			
		||||
            @RequestAttribute(value = "shoppingCart") ShoppingCart shoppingCart,
 | 
			
		||||
            @RequestParam("address") String address,
 | 
			
		||||
            @RequestParam("cardnumber") String cardnumber,
 | 
			
		||||
            @RequestParam("shopping_cart_revision") Integer cartRevision,
 | 
			
		||||
            @RequestParam("expected_total") Integer expectedPrice
 | 
			
		||||
    ) {
 | 
			
		||||
 | 
			
		||||
        // Must be refetched for persitence.
 | 
			
		||||
        user = userRepository.findById(user.id).get();
 | 
			
		||||
 | 
			
		||||
        CreateOrderAction action = new CreateOrderAction(
 | 
			
		||||
                user,
 | 
			
		||||
                expectedPrice,
 | 
			
		||||
                Address.fromString(address),
 | 
			
		||||
                PaymentMethod.fromCreditCarNumber(cardnumber),
 | 
			
		||||
                bookingEntryRepository.getByUser(user).orElse(BookingAccountEntry.newUser(user)),
 | 
			
		||||
                bookingEntryRepository.getByVat().orElse(BookingAccountEntry.newVat()),
 | 
			
		||||
                bookingEntryRepository.getByMain().orElse(BookingAccountEntry.newMain())
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        for (ShoppingCart.ShoppingCartItem item : shoppingCart.getItems()) {
 | 
			
		||||
            Article article = articleRepository.findById(item.getArticleId()).get();
 | 
			
		||||
            action.addArticle(article, item.getAmount(), wbeseRepo.getByArticle(article));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        CreateOrderAction.Result result = action.finish();
 | 
			
		||||
 | 
			
		||||
        EnableTrackingAction.addTrackingInfo(result.customerOrder);
 | 
			
		||||
 | 
			
		||||
        customerOderRepository.save(result.customerOrder);
 | 
			
		||||
        bookingRepository.saveAll(result.bookings);
 | 
			
		||||
        warehouseBookingRepository.save(result.warehouseBooking);
 | 
			
		||||
 | 
			
		||||
        shoppingCart.clear();
 | 
			
		||||
 | 
			
		||||
        return "shop/checkoutFinish";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -14,12 +14,12 @@ public class Booking {
 | 
			
		||||
    // always >= 0
 | 
			
		||||
    public int amountCent;
 | 
			
		||||
 | 
			
		||||
    @ManyToOne(optional = true)
 | 
			
		||||
    @ManyToOne(optional = true, cascade = CascadeType.ALL)
 | 
			
		||||
    public BookingAccountEntry source;
 | 
			
		||||
 | 
			
		||||
    @ManyToOne(optional = true)
 | 
			
		||||
    @ManyToOne(optional = true, cascade = CascadeType.ALL)
 | 
			
		||||
    public BookingAccountEntry destination;
 | 
			
		||||
 | 
			
		||||
    @OneToOne(optional = false)
 | 
			
		||||
    @OneToOne(optional = false, cascade = CascadeType.ALL)
 | 
			
		||||
    public BookingReason reason;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -16,13 +16,49 @@ public class BookingAccountEntry {
 | 
			
		||||
 | 
			
		||||
    public int newSumCent;
 | 
			
		||||
 | 
			
		||||
    @ManyToOne(optional = true)
 | 
			
		||||
    @ManyToOne(optional = true, cascade = CascadeType.ALL)
 | 
			
		||||
    public User userAccount;
 | 
			
		||||
 | 
			
		||||
    @ManyToOne(optional = true)
 | 
			
		||||
    @ManyToOne(optional = true, cascade = CascadeType.ALL)
 | 
			
		||||
    public Supplier supplierAccount;
 | 
			
		||||
 | 
			
		||||
    public boolean isMainAccount;
 | 
			
		||||
    public boolean isVATAccount;
 | 
			
		||||
 | 
			
		||||
    public BookingAccountEntry copyAddAmount(int amountCent) {
 | 
			
		||||
        BookingAccountEntry e = new BookingAccountEntry();
 | 
			
		||||
 | 
			
		||||
        e.userAccount = userAccount;
 | 
			
		||||
        e.supplierAccount = supplierAccount;
 | 
			
		||||
        e.isMainAccount = isMainAccount;
 | 
			
		||||
        e.isVATAccount = isVATAccount;
 | 
			
		||||
 | 
			
		||||
        e.newSumCent = newSumCent + amountCent;
 | 
			
		||||
 | 
			
		||||
        return e;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static BookingAccountEntry newUser(User user) {
 | 
			
		||||
        BookingAccountEntry e = new BookingAccountEntry();
 | 
			
		||||
        e.userAccount = user;
 | 
			
		||||
        e.newSumCent = 0;
 | 
			
		||||
 | 
			
		||||
        return e;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static BookingAccountEntry newMain() {
 | 
			
		||||
        BookingAccountEntry e = new BookingAccountEntry();
 | 
			
		||||
        e.isMainAccount = true;
 | 
			
		||||
        e.newSumCent = 0;
 | 
			
		||||
 | 
			
		||||
        return e;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static BookingAccountEntry newVat() {
 | 
			
		||||
        BookingAccountEntry e = new BookingAccountEntry();
 | 
			
		||||
        e.isVATAccount = true;
 | 
			
		||||
        e.newSumCent = 0;
 | 
			
		||||
 | 
			
		||||
        return e;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -22,9 +22,22 @@ public class BookingReason {
 | 
			
		||||
    @ManyToOne(optional = true)
 | 
			
		||||
    public CustomerOrder customerOrder;
 | 
			
		||||
 | 
			
		||||
    @ManyToOne(optional = true)
 | 
			
		||||
    @OneToOne(optional = true, cascade = CascadeType.ALL)
 | 
			
		||||
    public CustomerPayment customerPayment;
 | 
			
		||||
 | 
			
		||||
    @ManyToOne(optional = true)
 | 
			
		||||
    public SupplierOrder supplierOrder;
 | 
			
		||||
 | 
			
		||||
    public BookingReason() {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ;
 | 
			
		||||
 | 
			
		||||
    public BookingReason(CustomerOrder order) {
 | 
			
		||||
        this.customerOrder = order;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public BookingReason(CustomerPayment customerPayment) {
 | 
			
		||||
        this.customerPayment = customerPayment;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -7,4 +7,11 @@ import javax.validation.constraints.NotNull;
 | 
			
		||||
public class PaymentMethod {
 | 
			
		||||
    @NotNull
 | 
			
		||||
    public String creditCardNumber;
 | 
			
		||||
 | 
			
		||||
    public static PaymentMethod fromCreditCarNumber(String cardnumber) {
 | 
			
		||||
        PaymentMethod m = new PaymentMethod();
 | 
			
		||||
        m.creditCardNumber = cardnumber;
 | 
			
		||||
 | 
			
		||||
        return m;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -4,7 +4,24 @@ import javax.persistence.Embeddable;
 | 
			
		||||
 | 
			
		||||
@Embeddable
 | 
			
		||||
public class Address {
 | 
			
		||||
    public String name;
 | 
			
		||||
    public String addressString;
 | 
			
		||||
    public String name = "";
 | 
			
		||||
    public String addressString = "";
 | 
			
		||||
    public String country = "DE";
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public String toString() {
 | 
			
		||||
        return name + "\n" + addressString;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static Address fromString(String addr) {
 | 
			
		||||
        Address a = new Address();
 | 
			
		||||
 | 
			
		||||
        String[] arr = addr.split("\n", 2);
 | 
			
		||||
        a.name = arr[0];
 | 
			
		||||
        if (arr.length > 1) {
 | 
			
		||||
            a.addressString = arr[1];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return a;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -24,7 +24,7 @@ public class CustomerOrder {
 | 
			
		||||
 | 
			
		||||
    @OneToMany(
 | 
			
		||||
            targetEntity = CustomerOrderPosition.class,
 | 
			
		||||
            mappedBy = "order"
 | 
			
		||||
            mappedBy = "order", cascade = CascadeType.ALL
 | 
			
		||||
    )
 | 
			
		||||
    public List<CustomerOrderPosition> positions = new ArrayList<>();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -6,12 +6,18 @@ import java.util.List;
 | 
			
		||||
// Not a db entity. Just for session storage
 | 
			
		||||
public class ShoppingCart {
 | 
			
		||||
 | 
			
		||||
    private final static int MAX_ITEMS = 10;
 | 
			
		||||
 | 
			
		||||
    private int revision;
 | 
			
		||||
    private ArrayList<ShoppingCartItem> items;
 | 
			
		||||
 | 
			
		||||
    public ShoppingCart() {
 | 
			
		||||
        revision = (int) Math.round(Math.random() * 0xFFFF);
 | 
			
		||||
        clear();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void clear() {
 | 
			
		||||
        items = new ArrayList<>();
 | 
			
		||||
        revision = (int) Math.round(Math.random() * 0xFFFF);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public List<ShoppingCartItem> getItems() {
 | 
			
		||||
@ -60,7 +66,7 @@ public class ShoppingCart {
 | 
			
		||||
            items.add(new ShoppingCartItem(quantity, article));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        items.removeIf(i -> i.getAmount() == 0);
 | 
			
		||||
        items.removeIf(i -> i.getAmount() <= 0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static class ShoppingCartItem {
 | 
			
		||||
@ -78,6 +84,9 @@ public class ShoppingCart {
 | 
			
		||||
 | 
			
		||||
        public void addAmount(int amount) {
 | 
			
		||||
            this.amount += amount;
 | 
			
		||||
            if (this.amount > MAX_ITEMS) {
 | 
			
		||||
                this.amount = MAX_ITEMS;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public long getArticleId() {
 | 
			
		||||
@ -86,6 +95,9 @@ public class ShoppingCart {
 | 
			
		||||
 | 
			
		||||
        public void setAmount(Integer amount) {
 | 
			
		||||
            this.amount = amount;
 | 
			
		||||
            if (this.amount > MAX_ITEMS) {
 | 
			
		||||
                this.amount = MAX_ITEMS;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -30,10 +30,10 @@ public class User {
 | 
			
		||||
    public boolean isEmployee;
 | 
			
		||||
 | 
			
		||||
    @Embedded
 | 
			
		||||
    private Address defaultDeliveryAddress;
 | 
			
		||||
    public Address defaultDeliveryAddress;
 | 
			
		||||
 | 
			
		||||
    @Embedded
 | 
			
		||||
    private PaymentMethod defaultPayment;
 | 
			
		||||
    public PaymentMethod defaultPayment;
 | 
			
		||||
 | 
			
		||||
    public long getId() {
 | 
			
		||||
        return id;
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,7 @@
 | 
			
		||||
package org.hso.ecommerce.entities.warehouse;
 | 
			
		||||
 | 
			
		||||
import org.hso.ecommerce.entities.booking.BookingReason;
 | 
			
		||||
 | 
			
		||||
import javax.persistence.*;
 | 
			
		||||
import javax.validation.constraints.NotNull;
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
@ -21,7 +23,10 @@ public class WarehouseBooking {
 | 
			
		||||
    public boolean isDone;
 | 
			
		||||
 | 
			
		||||
    @OneToMany(
 | 
			
		||||
            mappedBy = "booking"
 | 
			
		||||
            mappedBy = "booking", cascade = CascadeType.ALL
 | 
			
		||||
    )
 | 
			
		||||
    public List<WarehouseBookingPosition> positions = new ArrayList<>();
 | 
			
		||||
 | 
			
		||||
    @OneToOne(optional = false, cascade = CascadeType.ALL)
 | 
			
		||||
    public BookingReason reason;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -23,10 +23,6 @@ public class WarehouseBookingPosition {
 | 
			
		||||
 | 
			
		||||
    public int amount; // positive or negative
 | 
			
		||||
 | 
			
		||||
    @ManyToOne(optional = true)
 | 
			
		||||
    public WarehouseBookingPositionSlotEntry source;
 | 
			
		||||
 | 
			
		||||
    @ManyToOne(optional = true)
 | 
			
		||||
    public WarehouseBookingPositionSlotEntry destination;
 | 
			
		||||
 | 
			
		||||
    @ManyToOne(optional = true, cascade = CascadeType.ALL)
 | 
			
		||||
    public WarehouseBookingPositionSlotEntry slotEntry;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -16,8 +16,23 @@ public class WarehouseBookingPositionSlotEntry {
 | 
			
		||||
    @ManyToOne
 | 
			
		||||
    public Article article;
 | 
			
		||||
 | 
			
		||||
    public int newSumArticles;
 | 
			
		||||
    public int newSumWarehousePosition;
 | 
			
		||||
    // Can;t do, does not work when created in action.
 | 
			
		||||
    //public int newSumArticles;
 | 
			
		||||
    public int newSumSlot;
 | 
			
		||||
 | 
			
		||||
    public int slot;
 | 
			
		||||
 | 
			
		||||
    public WarehouseBookingPositionSlotEntry copyAddAmount(int amount) {
 | 
			
		||||
        WarehouseBookingPositionSlotEntry e = new WarehouseBookingPositionSlotEntry();
 | 
			
		||||
 | 
			
		||||
        e.article = article;
 | 
			
		||||
        e.slot = slot;
 | 
			
		||||
 | 
			
		||||
        e.newSumSlot = newSumSlot + amount;
 | 
			
		||||
 | 
			
		||||
        assert e.article.warehouseUnitsPerSlot >= e.newSumSlot;
 | 
			
		||||
        assert e.newSumSlot >= 0;
 | 
			
		||||
 | 
			
		||||
        return e;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -23,4 +23,11 @@ public class WarehouseBookingReason {
 | 
			
		||||
    public CustomerOrder customerOrder;
 | 
			
		||||
 | 
			
		||||
    public boolean isManuel;
 | 
			
		||||
 | 
			
		||||
    public WarehouseBookingReason() {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public WarehouseBookingReason(CustomerOrder order) {
 | 
			
		||||
        this.customerOrder = order;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,26 @@
 | 
			
		||||
package org.hso.ecommerce.repos.booking;
 | 
			
		||||
 | 
			
		||||
import org.hso.ecommerce.entities.booking.BookingAccountEntry;
 | 
			
		||||
import org.hso.ecommerce.entities.user.User;
 | 
			
		||||
import org.springframework.data.jpa.repository.JpaRepository;
 | 
			
		||||
import org.springframework.data.jpa.repository.Query;
 | 
			
		||||
import org.springframework.stereotype.Repository;
 | 
			
		||||
 | 
			
		||||
import java.util.Optional;
 | 
			
		||||
 | 
			
		||||
@Repository
 | 
			
		||||
public interface BookingAccountEntryRepository extends JpaRepository<BookingAccountEntry, Long> {
 | 
			
		||||
 | 
			
		||||
    @Query("SELECT e FROM BookingAccountEntry e WHERE e.userAccount = :user ORDER BY e.id DESC")
 | 
			
		||||
    Optional<BookingAccountEntry> getByUser(User user);
 | 
			
		||||
 | 
			
		||||
    @Query("SELECT e FROM BookingAccountEntry e WHERE e.isMainAccount = 1 ORDER BY e.id DESC")
 | 
			
		||||
    Optional<BookingAccountEntry> getByMain();
 | 
			
		||||
 | 
			
		||||
    @Query("SELECT e FROM BookingAccountEntry e WHERE e.isVATAccount = 1 ORDER BY e.id DESC")
 | 
			
		||||
    Optional<BookingAccountEntry> getByVat();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,12 @@
 | 
			
		||||
package org.hso.ecommerce.repos.booking;
 | 
			
		||||
 | 
			
		||||
import org.hso.ecommerce.entities.booking.Booking;
 | 
			
		||||
import org.springframework.data.jpa.repository.JpaRepository;
 | 
			
		||||
import org.springframework.stereotype.Repository;
 | 
			
		||||
 | 
			
		||||
@Repository
 | 
			
		||||
public interface BookingRepository extends JpaRepository<Booking, Long> {
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,11 @@
 | 
			
		||||
package org.hso.ecommerce.repos.shop;
 | 
			
		||||
 | 
			
		||||
import org.hso.ecommerce.entities.shop.CustomerOrder;
 | 
			
		||||
import org.springframework.data.jpa.repository.JpaRepository;
 | 
			
		||||
import org.springframework.stereotype.Repository;
 | 
			
		||||
 | 
			
		||||
@Repository
 | 
			
		||||
public interface CustomerOderRepository extends JpaRepository<CustomerOrder, Long> {
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,18 @@
 | 
			
		||||
package org.hso.ecommerce.repos.warehouse;
 | 
			
		||||
 | 
			
		||||
import org.hso.ecommerce.entities.shop.Article;
 | 
			
		||||
import org.hso.ecommerce.entities.warehouse.WarehouseBookingPositionSlotEntry;
 | 
			
		||||
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 WarehouseBookingPositionSlotEntryRepository extends JpaRepository<WarehouseBookingPositionSlotEntry, Long> {
 | 
			
		||||
 | 
			
		||||
    // TODO this is wrong. revisit.
 | 
			
		||||
    @Query("SELECT e FROM WarehouseBookingPositionSlotEntry e WHERE e.article = :article ORDER BY e.id DESC")
 | 
			
		||||
    List<WarehouseBookingPositionSlotEntry> getByArticle(Article article);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,11 @@
 | 
			
		||||
package org.hso.ecommerce.repos.warehouse;
 | 
			
		||||
 | 
			
		||||
import org.hso.ecommerce.entities.warehouse.WarehouseBooking;
 | 
			
		||||
import org.springframework.data.jpa.repository.JpaRepository;
 | 
			
		||||
import org.springframework.stereotype.Repository;
 | 
			
		||||
 | 
			
		||||
@Repository
 | 
			
		||||
public interface WarehouseBookingRepository extends JpaRepository<WarehouseBooking, Long> {
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -21,7 +21,17 @@
 | 
			
		||||
    </div>
 | 
			
		||||
    <nav></nav>
 | 
			
		||||
</div>
 | 
			
		||||
<main class="content-width sidebar-layout" style="min-height: 100vh;">
 | 
			
		||||
<main th:if="${checkoutItems.size() == 0}">
 | 
			
		||||
    <div class="detailflex m">
 | 
			
		||||
        <h2> Noch keine Artikel im Warenkorb. </h2>
 | 
			
		||||
        <p>
 | 
			
		||||
            <img th:src="@{/img/undraw_successful_purchase_secondary.svg}"/>
 | 
			
		||||
        </p>
 | 
			
		||||
        <a class="button" th:href="@{/}"> Weiter shoppen </a>
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
</main>
 | 
			
		||||
<main th:if="${checkoutItems.size() > 0}" class="content-width sidebar-layout" style="min-height: 100vh;">
 | 
			
		||||
    <div style="max-width: 45em; width: 100%;">
 | 
			
		||||
        <table>
 | 
			
		||||
            <tr>
 | 
			
		||||
@ -37,7 +47,9 @@
 | 
			
		||||
                            th:src="@{/shop/articles/${item.article.id}/image.jpg}" class="s"/></a></td>
 | 
			
		||||
                    <td><a th:href="@{/shop/articles/{id}(id = ${item.article.id})}"
 | 
			
		||||
                           th:text="${item.article.title}"></a></td>
 | 
			
		||||
                    <td><span th:text="${#numbers.formatDecimal(item.total, 1, 'POINT', 2, 'COMMA')}"></span> EUR</td>
 | 
			
		||||
                    <td><span
 | 
			
		||||
                            th:text="${#numbers.formatDecimal(item.article.getPriceGross(), 1, 'POINT', 2, 'COMMA')}"></span>
 | 
			
		||||
                        EUR <b>x</b></td>
 | 
			
		||||
                    <td>
 | 
			
		||||
                        <form method="POST" th:action="@{/shop/articles/{id}(id = ${item.article.id})}">
 | 
			
		||||
                            <input type="hidden" name="fastcheckout" value="true"/>
 | 
			
		||||
@ -45,11 +57,9 @@
 | 
			
		||||
                            <select name="quantity" size="1">
 | 
			
		||||
                                <option th:value="${item.amount}" th:text="${item.amount}" selected></option>
 | 
			
		||||
                                <option value="0">Entfernen</option>
 | 
			
		||||
                                <option value="1">1</option>
 | 
			
		||||
                                <option value="2">2</option>
 | 
			
		||||
                                <option value="3">3</option>
 | 
			
		||||
                                <option value="4">4</option>
 | 
			
		||||
                                <option value="5">5</option>
 | 
			
		||||
                                <option th:each="quantity : ${#numbers.sequence(1,10)}"
 | 
			
		||||
                                        th:value="${quantity}"
 | 
			
		||||
                                        th:text="${quantity}"></option>
 | 
			
		||||
                            </select>
 | 
			
		||||
                            <button class="small">Ändern</button>
 | 
			
		||||
                        </form>
 | 
			
		||||
@ -64,11 +74,16 @@
 | 
			
		||||
                <h1>Checkout</h1>
 | 
			
		||||
            </div>
 | 
			
		||||
            <div th:if="${user}">
 | 
			
		||||
                <input type="hidden" name="shopping_cart_revision" th:value="${shoppingCart.getRevision()}"/>
 | 
			
		||||
                <input type="hidden" name="expected_total" th:value="${checkoutTotals.total}"/>
 | 
			
		||||
 | 
			
		||||
                <h2>Lieferadresse:</h2>
 | 
			
		||||
                <textarea rows="5" class="full-width" type="text" name="address"
 | 
			
		||||
                          placeholder="Optional: Zusatz
Optional: Unternehmen
Straße Hausnummer
Postleitzeit Ort
Land">
 | 
			
		||||
                          placeholder="Name
Optional: Zusatz
Optional: Unternehmen
Straße Hausnummer
Postleitzeit Ort
Land"
 | 
			
		||||
                          th:text="${user.defaultDeliveryAddress != null ? user.defaultDeliveryAddress.toString() : ''}"
 | 
			
		||||
                          required>
 | 
			
		||||
Max Mustermann
 | 
			
		||||
Musterstraße 42
 | 
			
		||||
Musterstraße 4
 | 
			
		||||
42424 Mustertal
 | 
			
		||||
               </textarea>
 | 
			
		||||
            </div>
 | 
			
		||||
@ -78,12 +93,10 @@ Musterstraße 42
 | 
			
		||||
                    <input type="radio" name="type" value="priv" id="payment-card" required checked>
 | 
			
		||||
                    <label for="payment-card">Kartenzahlung</label> <br/>
 | 
			
		||||
                    <input class="full-width" type="text" id="cardnumber" name="cardnumber" placeholder="Kartennummer"
 | 
			
		||||
                           th:value="${user.defaultPayment != null ? user.defaultPayment.creditCardNumber : ''}"
 | 
			
		||||
                           pattern="[0-9]{6,16}"
 | 
			
		||||
                           required/>
 | 
			
		||||
                </fieldset>
 | 
			
		||||
                <fieldset>
 | 
			
		||||
                    <input class="" type="checkbox" id="bonus" name="bonus" checked/>
 | 
			
		||||
                    <label for="bonus"><h3>10 gesammelte Bonuspunkte verwenden</h3></label>
 | 
			
		||||
                </fieldset>
 | 
			
		||||
            </div>
 | 
			
		||||
            <div>
 | 
			
		||||
                <h2>Bestellübersicht</h2>
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user