diff --git a/prototype/src/main/java/org/hso/ecommerce/action/cronjob/ICronjob.java b/prototype/src/main/java/org/hso/ecommerce/action/cronjob/ICronjob.java deleted file mode 100644 index bf2f3d8..0000000 --- a/prototype/src/main/java/org/hso/ecommerce/action/cronjob/ICronjob.java +++ /dev/null @@ -1,29 +0,0 @@ -package org.hso.ecommerce.action.cronjob; - -import java.util.Calendar; - -public interface ICronjob { - /** - * Calculate the earliest cronjob execution time that happens after the given reference time. - * - * @param reference Position in time to start searching. The implementor is allowed to modify the reference time. - * @return A new Calendar instance (or the same) containing the time for next execution. - */ - Calendar nextExecution(Calendar reference); - - /** - * Calculate the latest cronjob execution time that happens before or exactly at the given refernce time. - * - * @param reference Position in time to start searching. The implementor is allowed to modify the reference time. - * @return A new Calendar instance (or the same) containing the time of the last execution. - */ - Calendar previousExecution(Calendar reference); - - /** - * Execute this cronjob. - * - * @param time The point in time this execution was scheduled. In case of a missed cronjob, the actual time of this - * call might be much later. - */ - void executeAt(Calendar time); -} diff --git a/prototype/src/main/java/org/hso/ecommerce/action/cronjob/ReadSupplierDataAction.java b/prototype/src/main/java/org/hso/ecommerce/action/cronjob/ReadSupplierDataAction.java new file mode 100644 index 0000000..50930b8 --- /dev/null +++ b/prototype/src/main/java/org/hso/ecommerce/action/cronjob/ReadSupplierDataAction.java @@ -0,0 +1,83 @@ +package org.hso.ecommerce.action.cronjob; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Objects; + +import org.hso.ecommerce.api.SupplierService; +import org.hso.ecommerce.api.data.Article; +import org.hso.ecommerce.api.data.Supplier; + +public class ReadSupplierDataAction { + private List suppliers; + + public static class ArticleIdentifier { + public final String manufacturer; + public final String articleNumber; + + public ArticleIdentifier(String manufacturer, String articleNumber) { + this.manufacturer = manufacturer; + this.articleNumber = articleNumber; + } + + @Override + public int hashCode() { + return Objects.hash(manufacturer, articleNumber); + } + + @Override + public boolean equals(Object other) { + if (!(other instanceof ArticleIdentifier)) { + return false; + } + ArticleIdentifier otherId = (ArticleIdentifier) other; + return this.manufacturer.equals(otherId.manufacturer) && this.articleNumber.equals(otherId.articleNumber); + } + } + + public ReadSupplierDataAction(List suppliers) { + this.suppliers = suppliers; + } + + public static class Offer { + public final org.hso.ecommerce.entities.supplier.Supplier dbSupplier; + public final Supplier apiSupplier; + + public Offer(org.hso.ecommerce.entities.supplier.Supplier dbSupplier, Supplier apiSupplier) { + this.dbSupplier = dbSupplier; + this.apiSupplier = apiSupplier; + } + } + + public static class Result { + public final ArrayList supplierData; + public final HashMap cheapestOffer; + + public Result(ArrayList supplierData, HashMap cheapestOffer) { + this.supplierData = supplierData; + this.cheapestOffer = cheapestOffer; + } + } + + public Result finish() { + ArrayList suppliers = new ArrayList<>(); + HashMap price = new HashMap<>(); + HashMap cheapest = new HashMap<>(); + for (org.hso.ecommerce.entities.supplier.Supplier supplier : this.suppliers) { + SupplierService service = new SupplierService(supplier.apiUrl); + Supplier apiSupplier = service.getSupplier(); + suppliers.add(apiSupplier); + for (Article article : apiSupplier.articles) { + ArticleIdentifier identifier = new ArticleIdentifier(article.manufacturer, article.articleNumber); + Integer previousPrice = price.get(identifier); + if (previousPrice == null || article.pricePerUnitNet < previousPrice) { + price.put(identifier, article.pricePerUnitNet); + cheapest.put(identifier, new Offer(supplier, apiSupplier)); + } + } + } + + return new Result(suppliers, cheapest); + } +} diff --git a/prototype/src/main/java/org/hso/ecommerce/action/cronjob/Reorder.java b/prototype/src/main/java/org/hso/ecommerce/action/cronjob/Reorder.java deleted file mode 100644 index 212f696..0000000 --- a/prototype/src/main/java/org/hso/ecommerce/action/cronjob/Reorder.java +++ /dev/null @@ -1,38 +0,0 @@ -package org.hso.ecommerce.action.cronjob; - -import java.util.Calendar; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class Reorder implements ICronjob { - private static final Logger log = LoggerFactory.getLogger(Reorder.class); - - @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; - } - - @Override - public void executeAt(Calendar time) { - log.info("Executing Reorder Cronjob"); - } -} diff --git a/prototype/src/main/java/org/hso/ecommerce/action/cronjob/ReorderAction.java b/prototype/src/main/java/org/hso/ecommerce/action/cronjob/ReorderAction.java new file mode 100644 index 0000000..2bad0e0 --- /dev/null +++ b/prototype/src/main/java/org/hso/ecommerce/action/cronjob/ReorderAction.java @@ -0,0 +1,119 @@ +package org.hso.ecommerce.action.cronjob; + +import java.sql.Timestamp; +import java.util.HashMap; +import java.util.List; + +import org.hso.ecommerce.action.cronjob.ReadSupplierDataAction.ArticleIdentifier; +import org.hso.ecommerce.action.cronjob.ReadSupplierDataAction.Offer; +import org.hso.ecommerce.api.SupplierService; +import org.hso.ecommerce.api.data.Order; +import org.hso.ecommerce.api.data.OrderConfirmation; +import org.hso.ecommerce.entities.shop.Article; +import org.hso.ecommerce.entities.supplier.ArticleOffer; +import org.hso.ecommerce.entities.supplier.SupplierOrder; +import org.hso.ecommerce.entities.warehouse.WarehouseBookingPositionSlotEntry; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ReorderAction { + private static final Logger log = LoggerFactory.getLogger(ReorderAction.class); + + private Article article; + private Integer[] orderedAmounts; + private Integer undeliveredReorders; + private List inStock; + private HashMap cheapestOffer; + private HashMap articleOffers; + + public ReorderAction( + Article article, Integer[] orderedAmounts, + Integer undeliveredReorders, + List inStock, + HashMap cheapestOffer, + HashMap articleOffers + ) { + this.article = article; + this.orderedAmounts = orderedAmounts; + this.undeliveredReorders = undeliveredReorders; + this.inStock = inStock; + this.cheapestOffer = cheapestOffer; + this.articleOffers = articleOffers; + } + + private int null_to_zero(Integer input) { + return input == null ? 0 : input; + } + + private int getAmountInStock() { + int sum = 0; + for (WarehouseBookingPositionSlotEntry entry : inStock) { + sum += entry.newSumSlot; + } + return sum; + } + + private int calculateAmountToReorder() { + // Algorithm as described in the documentation + int a = null_to_zero(orderedAmounts[0]); + int b = null_to_zero(orderedAmounts[1]); + int c = null_to_zero(orderedAmounts[2]); + + int x = Math.max(Math.max(a, b), c); + int y = Math.min(Math.min(a, b), c); + + int n = 6 * x - 2 * y; + if (n < 3) { + n = 3; + } + + int i = null_to_zero(undeliveredReorders); + int l = getAmountInStock(); + + int o = n - i - l; + + return o; + } + + public SupplierOrder finish() { + if (!article.shouldReorder) { + return null; + } + + int amount = calculateAmountToReorder(); + if (amount <= 0) { + return null; + } + + ArticleIdentifier identifier = new ArticleIdentifier(article.related.manufacturer, article.related.articleNumber); + Offer offer = cheapestOffer.get(identifier); + if (offer == null) { + log.info("Could not order \"" + article.title + "\" because there is no supplier delivering it."); + return null; + } + + ArticleOffer articleOffer = articleOffers.get(identifier); + org.hso.ecommerce.api.data.Article apiArticle = offer.apiSupplier.findArticle(identifier.manufacturer, + identifier.articleNumber); + if (apiArticle.pricePerUnitNet > article.reorderMaxPrice) { + log.info("Could not order \"" + article.title + "\" because it is currently too expensive."); + return null; + } + + Order order = new Order(); + order.manufacturer = articleOffer.manufacturer; + order.articleNumber = articleOffer.articleNumber; + order.quantity = amount; + order.maxTotalPriceCentNet = apiArticle.pricePerUnitNet * amount; + + OrderConfirmation confirm = new SupplierService(offer.dbSupplier.apiUrl).order(order); + SupplierOrder createdOrder = new SupplierOrder(); + createdOrder.created = new Timestamp(System.currentTimeMillis()); + createdOrder.supplier = offer.dbSupplier; + createdOrder.ordered = articleOffer; + createdOrder.numberOfUnits = confirm.quantity; + createdOrder.pricePerUnitNetCent = confirm.pricePerUnitNetCent; + createdOrder.totalPriceNet = confirm.totalPriceNetCharged; + return createdOrder; + } +} 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 new file mode 100644 index 0000000..3046f2f --- /dev/null +++ b/prototype/src/main/java/org/hso/ecommerce/action/cronjob/UpdateOffersAction.java @@ -0,0 +1,49 @@ +package org.hso.ecommerce.action.cronjob; + +import java.util.HashMap; +import java.util.List; +import java.util.Map.Entry; + +import org.hso.ecommerce.action.cronjob.ReadSupplierDataAction.ArticleIdentifier; +import org.hso.ecommerce.action.cronjob.ReadSupplierDataAction.Offer; +import org.hso.ecommerce.api.data.Article; +import org.hso.ecommerce.entities.supplier.ArticleOffer; + +public class UpdateOffersAction { + private List offers; + private HashMap cheapestOffer; + + public UpdateOffersAction(List offers, HashMap cheapestOffer) { + this.offers = offers; + this.cheapestOffer = cheapestOffer; + } + + private HashMap mapOffers() { + HashMap map = new HashMap<>(); + for (ArticleOffer offer : offers) { + ArticleIdentifier identifier = new ArticleIdentifier(offer.manufacturer, offer.articleNumber); + map.put(identifier, offer); + } + return map; + } + + public List finish() { + HashMap availableOffers = mapOffers(); + for (Entry cheapestOffer : cheapestOffer.entrySet()) { + String manufacturer = cheapestOffer.getKey().manufacturer; + String articleNumber = cheapestOffer.getKey().articleNumber; + ArticleOffer currentOffer = availableOffers.get(cheapestOffer.getKey()); + if (currentOffer == null) { + currentOffer = new ArticleOffer(); + currentOffer.manufacturer = manufacturer; + currentOffer.articleNumber = articleNumber; + offers.add(currentOffer); + } + Article currentOfferedArticle = cheapestOffer.getValue().apiSupplier.findArticle(manufacturer, + articleNumber); + currentOffer.vatPercent = currentOfferedArticle.vatPercent; + currentOffer.shouldBeAdvertised = currentOfferedArticle.shouldBeAdvertised; + } + return offers; + } +} diff --git a/prototype/src/main/java/org/hso/ecommerce/api/data/Supplier.java b/prototype/src/main/java/org/hso/ecommerce/api/data/Supplier.java index 4ed1f7b..211f353 100644 --- a/prototype/src/main/java/org/hso/ecommerce/api/data/Supplier.java +++ b/prototype/src/main/java/org/hso/ecommerce/api/data/Supplier.java @@ -8,4 +8,14 @@ public class Supplier { public String name; public SupplierDiscount discount; public List
articles; + + public Article findArticle(String manufacturer, String articleNumber) { + for (Article a : articles) { + if (a.manufacturer.equals(manufacturer) && a.articleNumber.equals(articleNumber)) { + return a; + } + } + + return null; + } } 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 4f58c58..143f1cf 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 @@ -5,18 +5,206 @@ import java.util.Calendar; import java.util.Collections; import java.util.GregorianCalendar; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.Map.Entry; + import javax.annotation.PostConstruct; -import org.hso.ecommerce.action.cronjob.ICronjob; -import org.hso.ecommerce.action.cronjob.Reorder; + +import org.hso.ecommerce.action.booking.CreateBookingAction; +import org.hso.ecommerce.action.cronjob.ReadSupplierDataAction; +import org.hso.ecommerce.action.cronjob.ReadSupplierDataAction.ArticleIdentifier; +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.cron.BackgroundJob; +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.hso.ecommerce.entities.warehouse.WarehouseBookingPositionSlotEntry; +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.supplier.ArticleOfferRepository; +import org.hso.ecommerce.repos.supplier.SupplierOrderRepository; +import org.hso.ecommerce.repos.supplier.SupplierRepository; +import org.hso.ecommerce.repos.warehouse.WarehouseBookingPositionSlotEntryRepository; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +interface ICronjob { + /** + * Calculate the earliest cronjob execution time that happens after the given reference time. + * + * @param reference Position in time to start searching. The implementor is allowed to modify the reference time. + * @return A new Calendar instance (or the same) containing the time for next execution. + */ + Calendar nextExecution(Calendar reference); + + /** + * Calculate the latest cronjob execution time that happens before or exactly at the given refernce time. + * + * @param reference Position in time to start searching. The implementor is allowed to modify the reference time. + * @return A new Calendar instance (or the same) containing the time of the last execution. + */ + Calendar previousExecution(Calendar reference); + + /** + * Execute this cronjob. + * + * @param time The point in time this execution was scheduled. In case of a missed cronjob, the actual time of + * this call might be much later. + * @param controller Back-reference that allows to use repositories. + */ + void executeAt(Calendar time, CronjobController controller); +} + +@Component +class Reorder implements ICronjob { + private static final Logger log = LoggerFactory.getLogger(Reorder.class); + + @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) { + ArticleIdentifier identifier = new 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); + + List inStock = controller.warehouseBookingPositionSlotEntryRepository + .getByArticle(article.id); + + ReorderAction action = new ReorderAction(article, orderedAmounts, + undeliveredReorders, + inStock, + 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); + } + } + } +} + class ScheduledCronjob { public final Calendar executionTime; public final ICronjob cronjob; @@ -38,6 +226,30 @@ class CronjobController { @Autowired private final BackgroundJobRepository cronjobRepository = null; + @Autowired + final ArticleRepository articleRepository = null; + + @Autowired + final ArticleOfferRepository articleOfferRepository = null; + + @Autowired + final CustomerOderRepository customerOrderRepository = null; + + @Autowired + final BookingRepository bookingRepository = null; + + @Autowired + final BookingAccountEntryRepository bookingAccountEntryRepository = null; + + @Autowired + final WarehouseBookingPositionSlotEntryRepository warehouseBookingPositionSlotEntryRepository = null; + + @Autowired + final SupplierRepository supplierRepository = null; + + @Autowired + final SupplierOrderRepository supplierOrderRepository = null; + private static Map getCronjobs() { HashMap map = new HashMap<>(); @@ -49,7 +261,7 @@ class CronjobController { private ScheduledCronjob getNextCronjob() { Calendar currentTime = new GregorianCalendar(); - Iterable jobs = cronjobRepository.getAllJobs(); + Iterable jobs = cronjobRepository.findAll(); HashMap alreadyExecuted = new HashMap<>(); for (BackgroundJob job : jobs) { alreadyExecuted.put(job.jobName, job); @@ -100,7 +312,12 @@ class CronjobController { Thread.sleep(waitingTime); } - nextJob.cronjob.executeAt(nextJob.executionTime); + try { + nextJob.cronjob.executeAt(nextJob.executionTime, this); + } catch (Throwable t) { + log.error("Failed to execute cronjob " + nextJob.cronjob.getClass() + ":"); + t.printStackTrace(); + } nextJob.model.lastExecution = new Timestamp(nextJob.executionTime.getTimeInMillis()); cronjobRepository.save(nextJob.model); diff --git a/prototype/src/main/java/org/hso/ecommerce/entities/booking/BookingAccountEntry.java b/prototype/src/main/java/org/hso/ecommerce/entities/booking/BookingAccountEntry.java index 04b3b8a..64f2931 100644 --- a/prototype/src/main/java/org/hso/ecommerce/entities/booking/BookingAccountEntry.java +++ b/prototype/src/main/java/org/hso/ecommerce/entities/booking/BookingAccountEntry.java @@ -16,10 +16,10 @@ public class BookingAccountEntry { public int newSumCent; - @ManyToOne(optional = true, cascade = CascadeType.ALL) + @ManyToOne(optional = true, cascade = CascadeType.MERGE) public User userAccount; - @ManyToOne(optional = true, cascade = CascadeType.ALL) + @ManyToOne(optional = true, cascade = CascadeType.MERGE) public Supplier supplierAccount; public boolean isMainAccount; @@ -46,6 +46,14 @@ public class BookingAccountEntry { return e; } + public static BookingAccountEntry newSupplier(Supplier supplier) { + BookingAccountEntry e = new BookingAccountEntry(); + e.supplierAccount = supplier; + e.newSumCent = 0; + + return e; + } + public static BookingAccountEntry newMain() { BookingAccountEntry e = new BookingAccountEntry(); e.isMainAccount = true; 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 78e8ab5..3b93517 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 @@ -39,4 +39,8 @@ public class BookingReason { public BookingReason(CustomerPayment customerPayment) { this.customerPayment = customerPayment; } + + public BookingReason(SupplierOrder supplierOrder) { + this.supplierOrder = supplierOrder; + } } diff --git a/prototype/src/main/java/org/hso/ecommerce/repos/booking/BookingAccountEntryRepository.java b/prototype/src/main/java/org/hso/ecommerce/repos/booking/BookingAccountEntryRepository.java index d842a3a..53f0d62 100644 --- a/prototype/src/main/java/org/hso/ecommerce/repos/booking/BookingAccountEntryRepository.java +++ b/prototype/src/main/java/org/hso/ecommerce/repos/booking/BookingAccountEntryRepository.java @@ -1,18 +1,21 @@ package org.hso.ecommerce.repos.booking; +import java.util.Optional; + import org.hso.ecommerce.entities.booking.BookingAccountEntry; 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 { @Query(value = "SELECT * FROM booking_account_entries as e WHERE e.user_account_id = :user ORDER BY e.id DESC LIMIT 1", nativeQuery = true) Optional getByUser(Long user); + @Query(value = "SELECT * FROM booking_account_entries as e WHERE e.supplier_account_id = :supplier ORDER BY e.id DESC LIMIT 1", nativeQuery = true) + Optional getBySupplier(Long supplier); + @Query(value = "SELECT * FROM booking_account_entries as e WHERE e.is_main_account = 1 ORDER BY e.id DESC LIMIT 1", nativeQuery = true) Optional getByMain(); diff --git a/prototype/src/main/java/org/hso/ecommerce/repos/cronjob/BackgroundJobRepository.java b/prototype/src/main/java/org/hso/ecommerce/repos/cronjob/BackgroundJobRepository.java index a3aad66..41163d0 100644 --- a/prototype/src/main/java/org/hso/ecommerce/repos/cronjob/BackgroundJobRepository.java +++ b/prototype/src/main/java/org/hso/ecommerce/repos/cronjob/BackgroundJobRepository.java @@ -2,11 +2,9 @@ package org.hso.ecommerce.repos.cronjob; import org.hso.ecommerce.entities.cron.BackgroundJob; import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Query; import org.springframework.stereotype.Repository; @Repository public interface BackgroundJobRepository extends JpaRepository { - @Query(value = "SELECT * FROM background_jobs", nativeQuery = true) - Iterable getAllJobs(); + } diff --git a/prototype/src/main/java/org/hso/ecommerce/repos/shop/CustomerOderRepository.java b/prototype/src/main/java/org/hso/ecommerce/repos/shop/CustomerOderRepository.java index 407f45c..2c332f5 100644 --- a/prototype/src/main/java/org/hso/ecommerce/repos/shop/CustomerOderRepository.java +++ b/prototype/src/main/java/org/hso/ecommerce/repos/shop/CustomerOderRepository.java @@ -2,10 +2,16 @@ package org.hso.ecommerce.repos.shop; import org.hso.ecommerce.entities.shop.CustomerOrder; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; import org.springframework.stereotype.Repository; @Repository public interface CustomerOderRepository 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( + long articleId, java.sql.Timestamp begin, java.sql.Timestamp end + ); + } diff --git a/prototype/src/main/java/org/hso/ecommerce/repos/supplier/ArticleOfferRepository.java b/prototype/src/main/java/org/hso/ecommerce/repos/supplier/ArticleOfferRepository.java new file mode 100644 index 0000000..41263ff --- /dev/null +++ b/prototype/src/main/java/org/hso/ecommerce/repos/supplier/ArticleOfferRepository.java @@ -0,0 +1,8 @@ +package org.hso.ecommerce.repos.supplier; + +import org.hso.ecommerce.entities.supplier.ArticleOffer; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface ArticleOfferRepository extends JpaRepository { + +} 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 new file mode 100644 index 0000000..9d15e02 --- /dev/null +++ b/prototype/src/main/java/org/hso/ecommerce/repos/supplier/SupplierOrderRepository.java @@ -0,0 +1,14 @@ +package org.hso.ecommerce.repos.supplier; + +import org.hso.ecommerce.entities.supplier.SupplierOrder; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.stereotype.Repository; + +@Repository +public interface SupplierOrderRepository extends JpaRepository { + + @Query("SELECT SUM(so.numberOfUnits) FROM SupplierOrder so JOIN so.ordered ao WHERE ao.articleNumber = :articleNumber AND so.delivered IS NULL") + Integer countUndeliveredReorders(String articleNumber); + +} 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 new file mode 100644 index 0000000..2b81659 --- /dev/null +++ b/prototype/src/main/java/org/hso/ecommerce/repos/supplier/SupplierRepository.java @@ -0,0 +1,10 @@ +package org.hso.ecommerce.repos.supplier; + +import org.hso.ecommerce.entities.supplier.Supplier; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface SupplierRepository extends JpaRepository { + +}