package org.hso.ecommerce.controller.cronjob; import org.hso.ecommerce.action.booking.CreateBookingAction; import org.hso.ecommerce.action.cronjob.ReadSupplierDataAction; import org.hso.ecommerce.action.cronjob.ReorderAction; import org.hso.ecommerce.action.cronjob.UpdateOffersAction; 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.entities.shop.Article; import org.hso.ecommerce.entities.supplier.ArticleOffer; import org.hso.ecommerce.entities.supplier.Supplier; import org.hso.ecommerce.entities.supplier.SupplierOrder; import org.springframework.stereotype.Component; import java.sql.Timestamp; import java.util.Calendar; import java.util.HashMap; import java.util.List; @Component class Reorder implements ICronjob { @Override public String getDisplayName() { return "Nachbestellung"; } @Override public Calendar nextExecution(Calendar reference) { if (reference.get(Calendar.HOUR_OF_DAY) >= 8) { reference.add(Calendar.DAY_OF_MONTH, 1); } reference.set(Calendar.HOUR_OF_DAY, 8); reference.set(Calendar.MINUTE, 0); reference.set(Calendar.SECOND, 0); reference.set(Calendar.MILLISECOND, 0); return reference; } @Override public Calendar previousExecution(Calendar reference) { if (reference.get(Calendar.HOUR_OF_DAY) < 8) { reference.add(Calendar.DAY_OF_MONTH, -1); } reference.set(Calendar.HOUR_OF_DAY, 8); reference.set(Calendar.MINUTE, 0); reference.set(Calendar.SECOND, 0); reference.set(Calendar.MILLISECOND, 0); return reference; } /** * Calculates the amount of ordered articles by customers for the given article type in the time between begin and * end. * * @param article The article to search orders for. * @param begin The start time for the search (included) * @param end The end time for the search (excluded) * @return The number of articles that were ordered by customers in the given range. */ private Integer getOrderedAmounts(Article article, Calendar begin, Calendar end, CronjobController controller) { return controller.customerOrderRepository.countOrdersOfArticleInTimespan( article.id, new Timestamp(begin.getTimeInMillis()), new Timestamp(end.getTimeInMillis())); } /** * Calculates the amount of ordered articles by customers for the given article type in the three days before the * given reference time. The return-array contains 3 fields: Index 0: Orders 72 to 48 hours ago; Index 1: Orders 48 * to 24 hours ago; Index 2: Orders 24 to 0 hours ago. * * @param article The article for which the customer orders are checked. * @param time The reference time to use for calculation of the last orders. * @return A 3-element array containing the orders of the last three days. */ private Integer[] getOrderedAmounts(Article article, Calendar time, CronjobController controller) { Calendar oneDayBefore = (Calendar) time.clone(); oneDayBefore.add(Calendar.DAY_OF_MONTH, -1); Calendar twoDaysBefore = (Calendar) time.clone(); twoDaysBefore.add(Calendar.DAY_OF_MONTH, -2); Calendar threeDaysBefore = (Calendar) time.clone(); threeDaysBefore.add(Calendar.DAY_OF_MONTH, -3); return new Integer[]{ // getOrderedAmounts(article, threeDaysBefore, twoDaysBefore, controller), // getOrderedAmounts(article, twoDaysBefore, oneDayBefore, controller), // getOrderedAmounts(article, oneDayBefore, time, controller), // }; } private HashMap mapArticleOffers(List articleOffers) { HashMap map = new HashMap<>(); for (ArticleOffer articleOffer : articleOffers) { ReadSupplierDataAction.ArticleIdentifier identifier = new ReadSupplierDataAction.ArticleIdentifier(articleOffer.manufacturer, articleOffer.articleNumber); map.put(identifier, articleOffer); } return map; } @Override public void executeAt(Calendar time, CronjobController controller) { List suppliers = controller.supplierRepository.findAll(); ReadSupplierDataAction.Result supplierData = new ReadSupplierDataAction(suppliers).finish(); // Save the new offers in the database List allOffers = controller.articleOfferRepository.findAll(); allOffers = new UpdateOffersAction(allOffers, supplierData.cheapestOffer).finish(); controller.articleOfferRepository.saveAll(allOffers); HashMap mappedOffers = mapArticleOffers(allOffers); // Reorder List
allArticles = controller.articleRepository.findAll(); for (Article article : allArticles) { Integer[] orderedAmounts = getOrderedAmounts(article, time, controller); Integer undeliveredReorders = controller.supplierOrderRepository .countUndeliveredReorders(article.related.articleNumber); int amountInStock = controller.warehouseBookingPositionSlotEntryRepository .getByArticle(article.id) .stream() .mapToInt(e -> e.newSumSlot) .sum(); ReorderAction action = new ReorderAction(article, orderedAmounts, undeliveredReorders, amountInStock, supplierData.cheapestOffer, mappedOffers); SupplierOrder order = action.finish(); if (order != null) { controller.supplierOrderRepository.save(order); // Create bookings for this order int netPrice = order.totalPriceNet; int vatPercent = order.ordered.vatPercent; int vatAmount = netPrice * vatPercent / 100; int grossPrice = netPrice + vatAmount; // Obligation towards the supplier BookingAccountEntry mainAccount = controller.bookingAccountEntryRepository.getByMain() .orElseGet(BookingAccountEntry::newMain); BookingAccountEntry supplierAccount = controller.bookingAccountEntryRepository .getBySupplier(order.supplier.id) .orElseGet(() -> BookingAccountEntry.newSupplier(order.supplier)); BookingReason obligationReason = new BookingReason(order); Booking obligationBooking = new CreateBookingAction(mainAccount, supplierAccount, obligationReason, grossPrice).finish(); controller.bookingRepository.save(obligationBooking); // Input Tax BookingAccountEntry vatAccount = controller.bookingAccountEntryRepository.getByVat() .orElseGet(BookingAccountEntry::newVat); mainAccount = controller.bookingAccountEntryRepository.getByMain().get(); BookingReason inputTaxReason = new BookingReason(order); Booking inputTaxBooking = new CreateBookingAction(vatAccount, mainAccount, inputTaxReason, vatAmount) .finish(); controller.bookingRepository.save(inputTaxBooking); } } } }