package org.hso.ecommerce.supplier; import org.hso.ecommerce.supplier.carrier.Avian; import org.hso.ecommerce.supplier.carrier.Carrier; import org.hso.ecommerce.supplier.carrier.Posaidon; import org.hso.ecommerce.supplier.carrier.Shredder; import org.hso.ecommerce.supplier.data.Article; import org.hso.ecommerce.supplier.data.Order; import org.hso.ecommerce.supplier.data.OrderConfirmation; import org.hso.ecommerce.supplier.data.Supplier; import org.springframework.web.bind.annotation.*; import javax.annotation.PostConstruct; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; @RestController public class RequestController { private final HashMap dailySalesVolumeCent = new HashMap<>(); private final HashMap knownSuppliers = new HashMap<>(); private final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd"); private final Carrier[] carriers = new Carrier[]{ new Avian(), new Posaidon(), new Shredder() }; @PostConstruct public void init() throws IOException { for (Supplier s : ConfigurationReader.read()) { knownSuppliers.put(s.id, s); } } @GetMapping("/") public List index() { return new ArrayList<>(knownSuppliers.values()); } @GetMapping("/{supplier}/") public Supplier supplier(HttpServletResponse res, @PathVariable("supplier") String supplierName) { Supplier s = knownSuppliers.get(supplierName); if (s == null) { res.setStatus(HttpServletResponse.SC_NOT_FOUND); } return s; } @PostMapping("/{supplier}/order") public OrderConfirmation order(HttpServletResponse res, @PathVariable("supplier") String supplierName, @RequestBody Order order) { Supplier s = knownSuppliers.get(supplierName); if (s == null) { res.setStatus(HttpServletResponse.SC_NOT_FOUND); return null; } String dateKey = simpleDateFormat.format(new Date()); int dailyVolume = dailySalesVolumeCent.getOrDefault(dateKey, 0); Article a = s.findArticle(order.manufacturer, order.articleNumber); if (a == null) { res.setStatus(HttpServletResponse.SC_BAD_REQUEST); return null; } int priceNet = a.pricePerUnitNet * order.quantity; int discountableNetAmount = 0; if (dailyVolume >= s.discount.minimumDailySalesVolumeNetCent) { // grant discount on the full price discountableNetAmount = priceNet; } else if (dailyVolume + priceNet > s.discount.minimumDailySalesVolumeNetCent) { // grant partial discount discountableNetAmount = dailyVolume + priceNet - s.discount.minimumDailySalesVolumeNetCent; } int discount = (discountableNetAmount * s.discount.percentDiscount) / 100; Carrier selectedCarrier = carriers[Math.abs((supplierName + java.time.LocalDate.now()).hashCode()) % carriers.length]; OrderConfirmation confirmation = new OrderConfirmation(); confirmation.articleNumber = order.articleNumber; confirmation.discountNetCent = discount; confirmation.pricePerUnitNetCent = a.pricePerUnitNet; confirmation.manufacturer = a.manufacturer; confirmation.quantity = order.quantity; confirmation.totalPriceNetCharged = priceNet - discount; confirmation.carrier = selectedCarrier.getName(); confirmation.trackingId = selectedCarrier.generateTrackingId(); confirmation.estimatedArrival = selectedCarrier.arrivalEstimate(); if (confirmation.totalPriceNetCharged > order.maxTotalPriceCentNet) { res.setStatus(HttpServletResponse.SC_EXPECTATION_FAILED); return null; } dailyVolume += confirmation.totalPriceNetCharged; dailySalesVolumeCent.put(dateKey, dailyVolume); return confirmation; } }