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"; } }