165 lines
7.6 KiB
Java
165 lines
7.6 KiB
Java
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<ReadSupplierDataAction.ArticleIdentifier, ArticleOffer> mapArticleOffers(List<ArticleOffer> articleOffers) {
|
|
HashMap<ReadSupplierDataAction.ArticleIdentifier, ArticleOffer> 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<Supplier> suppliers = controller.supplierRepository.findAll();
|
|
ReadSupplierDataAction.Result supplierData = new ReadSupplierDataAction(suppliers).finish();
|
|
|
|
// Save the new offers in the database
|
|
List<ArticleOffer> allOffers = controller.articleOfferRepository.findAll();
|
|
allOffers = new UpdateOffersAction(allOffers, supplierData.cheapestOffer).finish();
|
|
controller.articleOfferRepository.saveAll(allOffers);
|
|
|
|
HashMap<ReadSupplierDataAction.ArticleIdentifier, ArticleOffer> mappedOffers = mapArticleOffers(allOffers);
|
|
|
|
// Reorder
|
|
List<Article> 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);
|
|
}
|
|
}
|
|
}
|
|
}
|