From 537b83da4377065dd469352cf35c00fc7cc80964 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Michaluk?= Date: Sun, 10 Dec 2017 21:47:02 +0100 Subject: [PATCH] manual testing of api --- .../com/bottega/factory/AppConfiguration.java | 6 +- ... => DeliveryAutoPlannerORMRepository.java} | 3 +- .../DeliveryPlannerDefinitionDao.java | 7 +- ...eliveryPlannerDefinitionEventsMapping.java | 2 + .../projection/DeliveryForecastDao.java | 11 +- .../DeliveryForecastProjection.java | 4 +- .../forecasting/DemandEventsMapping.java | 8 +- .../demand/forecasting/DemandService.java | 1 + .../command/DemandAdjustmentDao.java | 15 +++ .../command/DemandAdjustmentEntity.java | 41 +++++++ .../demand/forecasting/command/Handler.java | 42 +++++++ .../forecasting/persistence/DemandDao.java | 1 - .../persistence/ProductDemandDao.java | 3 - .../projection/CurrentDemandDao.java | 7 +- .../ProductDescriptionEventsMapping.java | 4 + .../projection/ProductionDailyOutputDao.java | 7 +- .../projection/ProductionOutputDao.java | 11 +- .../ShortagePredictionEventsMapping.java | 4 +- .../calculation/ForecastORMProvider.java | 24 ++-- .../prediction/monitoring/ShortagesDao.java | 7 +- .../factory/stock/forecast/StockForecast.java | 4 + .../forecast/StockForecastController.java | 10 +- .../stock/forecast/StockForecastQuery.java | 28 +++-- .../factory/warehouse/WarehouseService.java | 4 +- .../com/bottega/tools/CommandRepository.java | 27 ++++ ...tionDao.java => ProjectionRepository.java} | 2 +- app-monolith/src/main/resources/tasks.txt | 33 ++--- .../resources/example.delivery.schema.json | 15 --- .../delivery-definitions.json | 17 +++ .../delivery-forecasts.json | 6 + .../demand-adjustments.json | 23 ++++ .../demand-forecasts.json | 6 + .../product-descriptions.json | 9 ++ .../production-outputs-daily.json | 5 + .../production-outputs.json | 7 ++ .../shortages.json | 11 ++ .../stock-forecasts.json | 116 ++++++++++++++++++ .../planning/DeliveriesSuggestion.java | 8 +- .../planning/DeliveryAutoPlanner.java | 2 +- .../demand/forecasting/AdjustDemand.java | 13 +- .../prediction/calculation/Forecast.java | 16 +-- .../{CurrentStock.java => Stock.java} | 2 +- .../ShortagesCalculationAssemblerTrait.groovy | 12 +- 43 files changed, 445 insertions(+), 139 deletions(-) rename app-monolith/src/main/java/pl/com/bottega/factory/delivery/planning/{DeliveryAutoPlannerRepository.java => DeliveryAutoPlannerORMRepository.java} (89%) create mode 100644 app-monolith/src/main/java/pl/com/bottega/factory/demand/forecasting/command/DemandAdjustmentDao.java create mode 100644 app-monolith/src/main/java/pl/com/bottega/factory/demand/forecasting/command/DemandAdjustmentEntity.java create mode 100644 app-monolith/src/main/java/pl/com/bottega/factory/demand/forecasting/command/Handler.java create mode 100644 app-monolith/src/main/java/pl/com/bottega/tools/CommandRepository.java rename app-monolith/src/main/java/pl/com/bottega/tools/{ProjectionDao.java => ProjectionRepository.java} (88%) delete mode 100644 app-monolith/src/test/resources/example.delivery.schema.json create mode 100644 app-monolith/src/test/resources/pl.com.bottega.factory.delivery.planning/delivery-definitions.json create mode 100644 app-monolith/src/test/resources/pl.com.bottega.factory.delivery.planning/delivery-forecasts.json create mode 100644 app-monolith/src/test/resources/pl.com.bottega.factory.demand.forecasting.command/demand-adjustments.json create mode 100644 app-monolith/src/test/resources/pl.com.bottega.factory.demand.forecasting.command/demand-forecasts.json create mode 100644 app-monolith/src/test/resources/pl.com.bottega.factory.product.management/product-descriptions.json create mode 100644 app-monolith/src/test/resources/pl.com.bottega.factory.production.planning/production-outputs-daily.json create mode 100644 app-monolith/src/test/resources/pl.com.bottega.factory.production.planning/production-outputs.json create mode 100644 app-monolith/src/test/resources/pl.com.bottega.factory.shortages.prediction.monitoring/shortages.json create mode 100644 app-monolith/src/test/resources/pl.com.bottega.factory.stock.forecast/stock-forecasts.json rename shortages-prediction-model/src/main/java/pl/com/bottega/factory/shortages/prediction/calculation/{CurrentStock.java => Stock.java} (82%) diff --git a/app-monolith/src/main/java/pl/com/bottega/factory/AppConfiguration.java b/app-monolith/src/main/java/pl/com/bottega/factory/AppConfiguration.java index 5a6aafd..8b3565e 100644 --- a/app-monolith/src/main/java/pl/com/bottega/factory/AppConfiguration.java +++ b/app-monolith/src/main/java/pl/com/bottega/factory/AppConfiguration.java @@ -5,12 +5,14 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.domain.EntityScan; import org.springframework.context.annotation.Bean; import org.springframework.data.jpa.convert.threeten.Jsr310JpaConverters; -import pl.com.bottega.factory.shortages.prediction.calculation.CurrentStock; +import org.springframework.scheduling.annotation.EnableScheduling; +import pl.com.bottega.factory.shortages.prediction.calculation.Stock; import pl.com.bottega.factory.warehouse.WarehouseService; import java.time.Clock; @SpringBootApplication +@EnableScheduling @EntityScan( basePackageClasses = {AppConfiguration.class, Jsr310JpaConverters.class} ) @@ -23,7 +25,7 @@ public class AppConfiguration { @Bean public WarehouseService warehouseService() { // mocked facade for external service - return refNo -> new CurrentStock(0, 0); + return refNo -> new Stock(1200, 700); } @Bean diff --git a/app-monolith/src/main/java/pl/com/bottega/factory/delivery/planning/DeliveryAutoPlannerRepository.java b/app-monolith/src/main/java/pl/com/bottega/factory/delivery/planning/DeliveryAutoPlannerORMRepository.java similarity index 89% rename from app-monolith/src/main/java/pl/com/bottega/factory/delivery/planning/DeliveryAutoPlannerRepository.java rename to app-monolith/src/main/java/pl/com/bottega/factory/delivery/planning/DeliveryAutoPlannerORMRepository.java index 87228a0..351c999 100644 --- a/app-monolith/src/main/java/pl/com/bottega/factory/delivery/planning/DeliveryAutoPlannerRepository.java +++ b/app-monolith/src/main/java/pl/com/bottega/factory/delivery/planning/DeliveryAutoPlannerORMRepository.java @@ -4,7 +4,6 @@ import lombok.AllArgsConstructor; import org.springframework.stereotype.Component; import pl.com.bottega.factory.delivery.planning.definition.DeliveryPlannerDefinitionDao; import pl.com.bottega.factory.delivery.planning.definition.DeliveryPlannerDefinitionEntity; -import pl.com.bottega.factory.product.management.RefNoId; import java.util.Collections; @@ -12,7 +11,7 @@ import static java.util.Optional.ofNullable; @Component @AllArgsConstructor -public class DeliveryAutoPlannerRepository { +public class DeliveryAutoPlannerORMRepository { DeliveryPlannerDefinitionDao dao; diff --git a/app-monolith/src/main/java/pl/com/bottega/factory/delivery/planning/definition/DeliveryPlannerDefinitionDao.java b/app-monolith/src/main/java/pl/com/bottega/factory/delivery/planning/definition/DeliveryPlannerDefinitionDao.java index 5b61018..a7e21ec 100644 --- a/app-monolith/src/main/java/pl/com/bottega/factory/delivery/planning/definition/DeliveryPlannerDefinitionDao.java +++ b/app-monolith/src/main/java/pl/com/bottega/factory/delivery/planning/definition/DeliveryPlannerDefinitionDao.java @@ -1,7 +1,6 @@ package pl.com.bottega.factory.delivery.planning.definition; -import org.springframework.data.repository.CrudRepository; -import org.springframework.data.repository.query.Param; +import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.rest.core.annotation.RepositoryRestResource; import org.springframework.data.rest.core.annotation.RestResource; import org.springframework.stereotype.Repository; @@ -9,7 +8,7 @@ import org.springframework.stereotype.Repository; @Repository @RepositoryRestResource( path = "delivery-definitions", collectionResourceRel = "delivery-definitions") -public interface DeliveryPlannerDefinitionDao extends CrudRepository { +public interface DeliveryPlannerDefinitionDao extends JpaRepository { @RestResource(path = "refNos", rel = "refNos") - DeliveryPlannerDefinitionEntity findByRefNo(@Param("refNo") String refNo); + DeliveryPlannerDefinitionEntity findByRefNo(String refNo); } diff --git a/app-monolith/src/main/java/pl/com/bottega/factory/delivery/planning/definition/DeliveryPlannerDefinitionEventsMapping.java b/app-monolith/src/main/java/pl/com/bottega/factory/delivery/planning/definition/DeliveryPlannerDefinitionEventsMapping.java index c0e58d9..2167f36 100644 --- a/app-monolith/src/main/java/pl/com/bottega/factory/delivery/planning/definition/DeliveryPlannerDefinitionEventsMapping.java +++ b/app-monolith/src/main/java/pl/com/bottega/factory/delivery/planning/definition/DeliveryPlannerDefinitionEventsMapping.java @@ -1,6 +1,7 @@ package pl.com.bottega.factory.delivery.planning.definition; import lombok.AllArgsConstructor; +import org.springframework.data.rest.core.annotation.HandleAfterCreate; import org.springframework.data.rest.core.annotation.HandleAfterSave; import org.springframework.data.rest.core.annotation.RepositoryEventHandler; import org.springframework.stereotype.Component; @@ -14,6 +15,7 @@ public class DeliveryPlannerDefinitionEventsMapping { private DeliveryForecastProjection projection; @HandleAfterSave + @HandleAfterCreate public void handle(DeliveryPlannerDefinitionEntity entity) { projection.handleDeliveryPlannerDefinitionChange(entity.getRefNo()); } diff --git a/app-monolith/src/main/java/pl/com/bottega/factory/delivery/planning/projection/DeliveryForecastDao.java b/app-monolith/src/main/java/pl/com/bottega/factory/delivery/planning/projection/DeliveryForecastDao.java index f8b2891..f553136 100644 --- a/app-monolith/src/main/java/pl/com/bottega/factory/delivery/planning/projection/DeliveryForecastDao.java +++ b/app-monolith/src/main/java/pl/com/bottega/factory/delivery/planning/projection/DeliveryForecastDao.java @@ -3,22 +3,23 @@ package pl.com.bottega.factory.delivery.planning.projection; import org.springframework.data.rest.core.annotation.RepositoryRestResource; import org.springframework.data.rest.core.annotation.RestResource; import org.springframework.stereotype.Repository; -import pl.com.bottega.tools.ProjectionDao; +import pl.com.bottega.tools.ProjectionRepository; -import java.time.Instant; import java.time.LocalDate; +import java.time.LocalDateTime; import java.util.List; @Repository @RepositoryRestResource(path = "delivery-forecasts", collectionResourceRel = "delivery-forecasts") -public interface DeliveryForecastDao extends ProjectionDao { +public interface DeliveryForecastDao extends ProjectionRepository { - @RestResource(exported = false) - List findByRefNoAndDateGreaterThanEqual(String refNo, Instant instant); + @RestResource(path = "refNos", rel = "refNos") + List findByRefNoAndTimeGreaterThanEqual(String refNo, LocalDateTime from); @RestResource(exported = false) void deleteByRefNoAndDate(String refNo, LocalDate date); @RestResource(exported = false) void deleteByRefNo(String refNo); + } diff --git a/app-monolith/src/main/java/pl/com/bottega/factory/delivery/planning/projection/DeliveryForecastProjection.java b/app-monolith/src/main/java/pl/com/bottega/factory/delivery/planning/projection/DeliveryForecastProjection.java index 8cb2d68..24a8c49 100644 --- a/app-monolith/src/main/java/pl/com/bottega/factory/delivery/planning/projection/DeliveryForecastProjection.java +++ b/app-monolith/src/main/java/pl/com/bottega/factory/delivery/planning/projection/DeliveryForecastProjection.java @@ -3,7 +3,7 @@ package pl.com.bottega.factory.delivery.planning.projection; import lombok.AllArgsConstructor; import org.springframework.stereotype.Component; import pl.com.bottega.factory.delivery.planning.DeliveryAutoPlanner; -import pl.com.bottega.factory.delivery.planning.DeliveryAutoPlannerRepository; +import pl.com.bottega.factory.delivery.planning.DeliveryAutoPlannerORMRepository; import pl.com.bottega.factory.demand.forecasting.Demand; import pl.com.bottega.factory.demand.forecasting.DemandEvents; import pl.com.bottega.factory.demand.forecasting.projection.CurrentDemandDao; @@ -20,7 +20,7 @@ public class DeliveryForecastProjection implements DemandEvents { private final Clock clock; private final DeliveryForecastDao forecastDao; private final CurrentDemandDao demandDao; - private final DeliveryAutoPlannerRepository planners; + private final DeliveryAutoPlannerORMRepository planners; @Override public void emit(DemandedLevelsChanged event) { diff --git a/app-monolith/src/main/java/pl/com/bottega/factory/demand/forecasting/DemandEventsMapping.java b/app-monolith/src/main/java/pl/com/bottega/factory/demand/forecasting/DemandEventsMapping.java index aae24db..6523da7 100644 --- a/app-monolith/src/main/java/pl/com/bottega/factory/demand/forecasting/DemandEventsMapping.java +++ b/app-monolith/src/main/java/pl/com/bottega/factory/demand/forecasting/DemandEventsMapping.java @@ -1,5 +1,6 @@ package pl.com.bottega.factory.demand.forecasting; +import lombok.AllArgsConstructor; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Component; import pl.com.bottega.factory.delivery.planning.projection.DeliveryForecastProjection; @@ -8,11 +9,12 @@ import pl.com.bottega.factory.shortages.prediction.ShortagePredictionEventsMappi @Lazy @Component +@AllArgsConstructor class DemandEventsMapping implements DemandEvents { - CurrentDemandProjection demands; - DeliveryForecastProjection deliveries; - ShortagePredictionEventsMapping predictions; + private final CurrentDemandProjection demands; + private final DeliveryForecastProjection deliveries; + private final ShortagePredictionEventsMapping predictions; @Override public void emit(DemandedLevelsChanged event) { diff --git a/app-monolith/src/main/java/pl/com/bottega/factory/demand/forecasting/DemandService.java b/app-monolith/src/main/java/pl/com/bottega/factory/demand/forecasting/DemandService.java index b95c0b7..039bd24 100644 --- a/app-monolith/src/main/java/pl/com/bottega/factory/demand/forecasting/DemandService.java +++ b/app-monolith/src/main/java/pl/com/bottega/factory/demand/forecasting/DemandService.java @@ -15,6 +15,7 @@ public class DemandService { public void process(Document document) { ProductDemand model = repository.get(document.getRefNo()); model.process(document); + repository.save(model); } public void adjust(AdjustDemand adjustDemand) { diff --git a/app-monolith/src/main/java/pl/com/bottega/factory/demand/forecasting/command/DemandAdjustmentDao.java b/app-monolith/src/main/java/pl/com/bottega/factory/demand/forecasting/command/DemandAdjustmentDao.java new file mode 100644 index 0000000..7098022 --- /dev/null +++ b/app-monolith/src/main/java/pl/com/bottega/factory/demand/forecasting/command/DemandAdjustmentDao.java @@ -0,0 +1,15 @@ +package pl.com.bottega.factory.demand.forecasting.command; + +import org.springframework.data.rest.core.annotation.RepositoryRestResource; +import org.springframework.data.rest.core.annotation.RestResource; +import org.springframework.stereotype.Repository; +import pl.com.bottega.tools.CommandRepository; + +import java.time.LocalDate; + +@Repository +@RepositoryRestResource(path = "demand-adjustments", collectionResourceRel = "demand-adjustments") +public interface DemandAdjustmentDao extends CommandRepository { + @RestResource(exported = false) + void deleteByCleanAfterGreaterThanEqual(LocalDate date); +} diff --git a/app-monolith/src/main/java/pl/com/bottega/factory/demand/forecasting/command/DemandAdjustmentEntity.java b/app-monolith/src/main/java/pl/com/bottega/factory/demand/forecasting/command/DemandAdjustmentEntity.java new file mode 100644 index 0000000..7d4fed7 --- /dev/null +++ b/app-monolith/src/main/java/pl/com/bottega/factory/demand/forecasting/command/DemandAdjustmentEntity.java @@ -0,0 +1,41 @@ +package pl.com.bottega.factory.demand.forecasting.command; + +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import pl.com.bottega.factory.demand.forecasting.AdjustDemand; +import pl.com.bottega.tools.JsonConverter; + +import javax.persistence.*; +import java.io.Serializable; +import java.time.LocalDate; + +@Entity(name = "DemandAdjustment") +@Getter +@NoArgsConstructor +@EqualsAndHashCode(of = "id") +public class DemandAdjustmentEntity implements Serializable { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private Long id; + + @Column + private String note; + @Column + private String customerRepresentative; + @Column + @Setter + private LocalDate cleanAfter; + + @Column(length = 4096) + @Convert(converter = AdjustDemandAsJson.class) + private AdjustDemand adjustment; + + public static class AdjustDemandAsJson extends JsonConverter { + public AdjustDemandAsJson() { + super(AdjustDemand.class); + } + } +} diff --git a/app-monolith/src/main/java/pl/com/bottega/factory/demand/forecasting/command/Handler.java b/app-monolith/src/main/java/pl/com/bottega/factory/demand/forecasting/command/Handler.java new file mode 100644 index 0000000..14d4ae1 --- /dev/null +++ b/app-monolith/src/main/java/pl/com/bottega/factory/demand/forecasting/command/Handler.java @@ -0,0 +1,42 @@ +package pl.com.bottega.factory.demand.forecasting.command; + +import lombok.AllArgsConstructor; +import org.springframework.boot.context.event.ApplicationReadyEvent; +import org.springframework.context.event.EventListener; +import org.springframework.data.rest.core.annotation.HandleBeforeCreate; +import org.springframework.data.rest.core.annotation.HandleBeforeSave; +import org.springframework.data.rest.core.annotation.RepositoryEventHandler; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; +import pl.com.bottega.factory.demand.forecasting.DemandService; + +import java.time.Clock; +import java.time.LocalDate; + +@Component +@AllArgsConstructor +@RepositoryEventHandler +public class Handler { + + private final DemandService service; + private final DemandAdjustmentDao adjustments; + private final Clock clock; + + @HandleBeforeCreate + @HandleBeforeSave + public void adjustDemand(DemandAdjustmentEntity resource) { + LocalDate latest = resource.getAdjustment() + .latestAdjustment() + .orElse(LocalDate.now(clock)); + resource.setCleanAfter(latest.plusDays(7)); + service.adjust(resource.getAdjustment()); + } + + @Scheduled(cron = "0 0 12 * * ?") + @EventListener(ApplicationReadyEvent.class) + @Transactional + public void clean() { + adjustments.deleteByCleanAfterGreaterThanEqual(LocalDate.now(clock)); + } +} diff --git a/app-monolith/src/main/java/pl/com/bottega/factory/demand/forecasting/persistence/DemandDao.java b/app-monolith/src/main/java/pl/com/bottega/factory/demand/forecasting/persistence/DemandDao.java index 3e3c218..0fd3e41 100644 --- a/app-monolith/src/main/java/pl/com/bottega/factory/demand/forecasting/persistence/DemandDao.java +++ b/app-monolith/src/main/java/pl/com/bottega/factory/demand/forecasting/persistence/DemandDao.java @@ -11,6 +11,5 @@ import java.util.List; @Repository @RestResource(exported = false) public interface DemandDao extends JpaRepository { - List findByProductRefNoAndDateGreaterThanEqual(String refNo, LocalDate now); } diff --git a/app-monolith/src/main/java/pl/com/bottega/factory/demand/forecasting/persistence/ProductDemandDao.java b/app-monolith/src/main/java/pl/com/bottega/factory/demand/forecasting/persistence/ProductDemandDao.java index c3c3e8c..dc874e6 100644 --- a/app-monolith/src/main/java/pl/com/bottega/factory/demand/forecasting/persistence/ProductDemandDao.java +++ b/app-monolith/src/main/java/pl/com/bottega/factory/demand/forecasting/persistence/ProductDemandDao.java @@ -8,8 +8,5 @@ import pl.com.bottega.factory.demand.forecasting.ProductDemandEntity; @Repository @RestResource(exported = false) public interface ProductDemandDao extends JpaRepository { - - ProductDemandEntity findById(Long id); - ProductDemandEntity findByRefNo(String refNo); } diff --git a/app-monolith/src/main/java/pl/com/bottega/factory/demand/forecasting/projection/CurrentDemandDao.java b/app-monolith/src/main/java/pl/com/bottega/factory/demand/forecasting/projection/CurrentDemandDao.java index e97e8da..d398b21 100644 --- a/app-monolith/src/main/java/pl/com/bottega/factory/demand/forecasting/projection/CurrentDemandDao.java +++ b/app-monolith/src/main/java/pl/com/bottega/factory/demand/forecasting/projection/CurrentDemandDao.java @@ -3,16 +3,15 @@ package pl.com.bottega.factory.demand.forecasting.projection; import org.springframework.data.rest.core.annotation.RepositoryRestResource; import org.springframework.data.rest.core.annotation.RestResource; import org.springframework.stereotype.Repository; -import pl.com.bottega.tools.ProjectionDao; +import pl.com.bottega.tools.ProjectionRepository; import java.time.LocalDate; import java.util.List; @Repository @RepositoryRestResource(path = "demand-forecasts", collectionResourceRel = "demand-forecasts") -public interface CurrentDemandDao extends ProjectionDao { - - @RestResource(exported = false) +public interface CurrentDemandDao extends ProjectionRepository { + @RestResource(path = "refNos", rel = "refNos") List findByRefNoAndDateGreaterThanEqual(String refNo, LocalDate date); @RestResource(exported = false) diff --git a/app-monolith/src/main/java/pl/com/bottega/factory/product/management/ProductDescriptionEventsMapping.java b/app-monolith/src/main/java/pl/com/bottega/factory/product/management/ProductDescriptionEventsMapping.java index 418583b..06607bc 100644 --- a/app-monolith/src/main/java/pl/com/bottega/factory/product/management/ProductDescriptionEventsMapping.java +++ b/app-monolith/src/main/java/pl/com/bottega/factory/product/management/ProductDescriptionEventsMapping.java @@ -1,14 +1,18 @@ package pl.com.bottega.factory.product.management; +import lombok.AllArgsConstructor; +import org.springframework.data.rest.core.annotation.HandleAfterCreate; import org.springframework.data.rest.core.annotation.HandleAfterSave; import org.springframework.data.rest.core.annotation.RepositoryEventHandler; import org.springframework.stereotype.Component; @Component +@AllArgsConstructor @RepositoryEventHandler public class ProductDescriptionEventsMapping { @HandleAfterSave + @HandleAfterCreate public void handle(ProductDescriptionEntity entity) { } } diff --git a/app-monolith/src/main/java/pl/com/bottega/factory/production/planning/projection/ProductionDailyOutputDao.java b/app-monolith/src/main/java/pl/com/bottega/factory/production/planning/projection/ProductionDailyOutputDao.java index d9ba987..cbb8fe9 100644 --- a/app-monolith/src/main/java/pl/com/bottega/factory/production/planning/projection/ProductionDailyOutputDao.java +++ b/app-monolith/src/main/java/pl/com/bottega/factory/production/planning/projection/ProductionDailyOutputDao.java @@ -1,15 +1,16 @@ package pl.com.bottega.factory.production.planning.projection; import org.springframework.data.rest.core.annotation.RepositoryRestResource; +import org.springframework.data.rest.core.annotation.RestResource; import org.springframework.stereotype.Repository; -import pl.com.bottega.tools.ProjectionDao; +import pl.com.bottega.tools.ProjectionRepository; import java.time.LocalDate; import java.util.List; @Repository @RepositoryRestResource(path = "production-outputs-daily", collectionResourceRel = "production-outputs-daily") -public interface ProductionDailyOutputDao extends ProjectionDao { - +public interface ProductionDailyOutputDao extends ProjectionRepository { + @RestResource(path = "refNos", rel = "refNos") List findByRefNoAndDateGreaterThanEqual(String refNo, LocalDate date); } diff --git a/app-monolith/src/main/java/pl/com/bottega/factory/production/planning/projection/ProductionOutputDao.java b/app-monolith/src/main/java/pl/com/bottega/factory/production/planning/projection/ProductionOutputDao.java index d765597..9f8bc6b 100644 --- a/app-monolith/src/main/java/pl/com/bottega/factory/production/planning/projection/ProductionOutputDao.java +++ b/app-monolith/src/main/java/pl/com/bottega/factory/production/planning/projection/ProductionOutputDao.java @@ -1,15 +1,16 @@ package pl.com.bottega.factory.production.planning.projection; import org.springframework.data.rest.core.annotation.RepositoryRestResource; +import org.springframework.data.rest.core.annotation.RestResource; import org.springframework.stereotype.Repository; -import pl.com.bottega.tools.ProjectionDao; +import pl.com.bottega.tools.ProjectionRepository; -import java.time.Instant; +import java.time.LocalDateTime; import java.util.List; @Repository @RepositoryRestResource(path = "production-outputs", collectionResourceRel = "production-outputs") -public interface ProductionOutputDao extends ProjectionDao { - - List findByRefNoAndStartGreaterThanEqual(String refNo, Instant instant); +public interface ProductionOutputDao extends ProjectionRepository { + @RestResource(path = "refNos", rel = "refNos") + List findByRefNoAndStartGreaterThanEqual(String refNo, LocalDateTime from); } diff --git a/app-monolith/src/main/java/pl/com/bottega/factory/shortages/prediction/ShortagePredictionEventsMapping.java b/app-monolith/src/main/java/pl/com/bottega/factory/shortages/prediction/ShortagePredictionEventsMapping.java index 1516953..a682098 100644 --- a/app-monolith/src/main/java/pl/com/bottega/factory/shortages/prediction/ShortagePredictionEventsMapping.java +++ b/app-monolith/src/main/java/pl/com/bottega/factory/shortages/prediction/ShortagePredictionEventsMapping.java @@ -7,14 +7,12 @@ import pl.com.bottega.factory.demand.forecasting.DemandEvents; import pl.com.bottega.factory.shortages.prediction.monitoring.ShortagePredictionProcess; import pl.com.bottega.factory.shortages.prediction.monitoring.ShortagePredictionProcessRepository; -import java.util.Set; - @Lazy @Component @AllArgsConstructor public class ShortagePredictionEventsMapping implements DemandEvents { - private ShortagePredictionProcessRepository repository; + private final ShortagePredictionProcessRepository repository; @Override public void emit(DemandedLevelsChanged event) { diff --git a/app-monolith/src/main/java/pl/com/bottega/factory/shortages/prediction/calculation/ForecastORMProvider.java b/app-monolith/src/main/java/pl/com/bottega/factory/shortages/prediction/calculation/ForecastORMProvider.java index 94bc4e5..a0700fe 100644 --- a/app-monolith/src/main/java/pl/com/bottega/factory/shortages/prediction/calculation/ForecastORMProvider.java +++ b/app-monolith/src/main/java/pl/com/bottega/factory/shortages/prediction/calculation/ForecastORMProvider.java @@ -12,9 +12,9 @@ import pl.com.bottega.factory.warehouse.WarehouseService; import java.time.Clock; import java.time.Instant; import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.List; import java.util.Map; +import java.util.SortedSet; +import java.util.TreeSet; import java.util.stream.Collectors; import static java.util.stream.Collectors.toMap; @@ -23,36 +23,36 @@ import static java.util.stream.Collectors.toMap; @AllArgsConstructor class ForecastORMProvider implements Forecasts { - private WarehouseService stocks; - private DeliveryForecastDao demands; - private ProductionOutputDao outputs; - private Clock clock; + private final WarehouseService stocks; + private final DeliveryForecastDao demands; + private final ProductionOutputDao outputs; + private final Clock clock; @Override public Forecast get(RefNoId refNo, int daysAhead) { - CurrentStock stock = stocks.forRefNo(refNo); + Stock stock = stocks.forRefNo(refNo); Instant now = Instant.now(clock); LocalDateTime time = now.atZone(clock.getZone()).toLocalDateTime(); Map demands = this.demands - .findByRefNoAndDateGreaterThanEqual(refNo.getRefNo(), now).stream() + .findByRefNoAndTimeGreaterThanEqual(refNo.getRefNo(), time).stream() .collect(toMap( DeliveryForecastEntity::getTime, DeliveryForecastEntity::getLevel )); - List times = new ArrayList<>(demands.keySet()); + SortedSet deliveryTimes = new TreeSet<>(demands.keySet()); Demands demand = new Demands(demands); ProductionOutputs outputs = new ProductionForecast( - this.outputs.findByRefNoAndStartGreaterThanEqual(refNo.getRefNo(), now).stream() + this.outputs.findByRefNoAndStartGreaterThanEqual(refNo.getRefNo(), time).stream() .map(e -> new Item( e.getStart(), e.getDuration(), e.getPartsPerMinute())) .collect(Collectors.toList()) - ).outputsInTimes(time, demands.keySet()); + ).outputsInTimes(time, deliveryTimes); - return new Forecast(refNo.getRefNo(), time, times, stock, outputs, demand); + return new Forecast(refNo.getRefNo(), time, deliveryTimes, stock, outputs, demand); } } diff --git a/app-monolith/src/main/java/pl/com/bottega/factory/shortages/prediction/monitoring/ShortagesDao.java b/app-monolith/src/main/java/pl/com/bottega/factory/shortages/prediction/monitoring/ShortagesDao.java index bf3751f..275bd20 100644 --- a/app-monolith/src/main/java/pl/com/bottega/factory/shortages/prediction/monitoring/ShortagesDao.java +++ b/app-monolith/src/main/java/pl/com/bottega/factory/shortages/prediction/monitoring/ShortagesDao.java @@ -1,16 +1,15 @@ package pl.com.bottega.factory.shortages.prediction.monitoring; -import org.springframework.data.repository.query.Param; import org.springframework.data.rest.core.annotation.RepositoryRestResource; import org.springframework.data.rest.core.annotation.RestResource; import org.springframework.stereotype.Repository; -import pl.com.bottega.tools.ProjectionDao; +import pl.com.bottega.tools.ProjectionRepository; import java.util.Optional; @Repository @RepositoryRestResource(path = "shortages", collectionResourceRel = "shortages") -public interface ShortagesDao extends ProjectionDao { +public interface ShortagesDao extends ProjectionRepository { @RestResource(path = "refNos", rel = "refNos") - Optional findByRefNo(@Param("refNo") String refNo); + Optional findByRefNo(String refNo); } diff --git a/app-monolith/src/main/java/pl/com/bottega/factory/stock/forecast/StockForecast.java b/app-monolith/src/main/java/pl/com/bottega/factory/stock/forecast/StockForecast.java index 8ac491e..ab19594 100644 --- a/app-monolith/src/main/java/pl/com/bottega/factory/stock/forecast/StockForecast.java +++ b/app-monolith/src/main/java/pl/com/bottega/factory/stock/forecast/StockForecast.java @@ -1,5 +1,6 @@ package pl.com.bottega.factory.stock.forecast; +import com.fasterxml.jackson.annotation.JsonFormat; import lombok.Builder; import lombok.Singular; import lombok.Value; @@ -8,6 +9,8 @@ import pl.com.bottega.factory.product.management.ProductDescription; import java.time.LocalDate; import java.util.List; +import static com.fasterxml.jackson.annotation.JsonFormat.Shape.STRING; + @Value @Builder class StockForecast { @@ -19,6 +22,7 @@ class StockForecast { @Value static class DailyForecast { + @JsonFormat(shape = STRING, pattern = "yyyy-MM-dd") LocalDate date; long stock; long withLocked; diff --git a/app-monolith/src/main/java/pl/com/bottega/factory/stock/forecast/StockForecastController.java b/app-monolith/src/main/java/pl/com/bottega/factory/stock/forecast/StockForecastController.java index 8248cb9..32d9a9e 100644 --- a/app-monolith/src/main/java/pl/com/bottega/factory/stock/forecast/StockForecastController.java +++ b/app-monolith/src/main/java/pl/com/bottega/factory/stock/forecast/StockForecastController.java @@ -4,21 +4,21 @@ import lombok.AllArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; import org.springframework.transaction.annotation.Transactional; -import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; import pl.com.bottega.factory.product.management.RefNoId; -//@Controller -//@RequestMapping("/stock/forecasts") +@Controller +@RequestMapping("stock-forecasts") @AllArgsConstructor class StockForecastController { private final StockForecastQuery query; - @RequestMapping(value = "/{refNo}", method = RequestMethod.GET) + @RequestMapping(value = "search/refNos", method = RequestMethod.GET) @Transactional(readOnly = true) - ResponseEntity get(@PathVariable("refNo") String refNo) { + ResponseEntity get(@RequestParam String refNo) { return ResponseEntity.ok(query.get(new RefNoId(refNo))); } } diff --git a/app-monolith/src/main/java/pl/com/bottega/factory/stock/forecast/StockForecastQuery.java b/app-monolith/src/main/java/pl/com/bottega/factory/stock/forecast/StockForecastQuery.java index efc0a5a..25cd988 100644 --- a/app-monolith/src/main/java/pl/com/bottega/factory/stock/forecast/StockForecastQuery.java +++ b/app-monolith/src/main/java/pl/com/bottega/factory/stock/forecast/StockForecastQuery.java @@ -11,7 +11,7 @@ import pl.com.bottega.factory.product.management.ProductDescriptionEntity; import pl.com.bottega.factory.product.management.RefNoId; import pl.com.bottega.factory.production.planning.projection.ProductionDailyOutputDao; import pl.com.bottega.factory.production.planning.projection.ProductionDailyOutputEntity; -import pl.com.bottega.factory.shortages.prediction.calculation.CurrentStock; +import pl.com.bottega.factory.shortages.prediction.calculation.Stock; import pl.com.bottega.factory.stock.forecast.StockForecast.StockForecastBuilder; import pl.com.bottega.factory.warehouse.WarehouseService; @@ -34,10 +34,12 @@ class StockForecastQuery { private final Clock clock; StockForecast get(RefNoId refNo) { - CurrentStock stock = stocks.forRefNo(refNo); + Stock stock = stocks.forRefNo(refNo); LocalDate today = LocalDate.now(clock); - return build(refNo, today, Optional.ofNullable(descriptions.findByRefNo(refNo.getRefNo())) - .map(ProductDescriptionEntity::getDescription).orElse(null), stock, + return build(refNo, today, + Optional.ofNullable(descriptions.findByRefNo(refNo.getRefNo())) + .map(ProductDescriptionEntity::getDescription).orElse(null), + stock, this.demands .findByRefNoAndDateGreaterThanEqual(refNo.getRefNo(), today).stream() .collect(toMap( @@ -49,25 +51,31 @@ class StockForecastQuery { .collect(toMap( ProductionDailyOutputEntity::getDate, ProductionDailyOutputEntity::getOutput - ))); + )) + ); } private StockForecast build(RefNoId refNo, LocalDate today, - ProductDescription description, CurrentStock stock, + ProductDescription description, Stock stock, Map demands, Map outputs) { LocalDate stopAtDay = today.plusDays(15); long level = stock.getLevel(); StockForecastBuilder builder = StockForecast.builder(); for (LocalDate date = today; date.isBefore(stopAtDay); date = date.plusDays(1)) { + long demand = demands.getOrDefault(date, 0L); + long output = outputs.getOrDefault(date, 0L); + long withLocked = level + stock.getLocked(); builder.forecast( new StockForecast.DailyForecast( date, level, - level + stock.getLocked(), - demands.getOrDefault(date, 0L), - outputs.getOrDefault(date, 0L) - )); + withLocked, + demand, + output + ) + ); + level = level - demand + output; } return builder .refNo(refNo.getRefNo()) diff --git a/app-monolith/src/main/java/pl/com/bottega/factory/warehouse/WarehouseService.java b/app-monolith/src/main/java/pl/com/bottega/factory/warehouse/WarehouseService.java index 212b490..e5d5089 100644 --- a/app-monolith/src/main/java/pl/com/bottega/factory/warehouse/WarehouseService.java +++ b/app-monolith/src/main/java/pl/com/bottega/factory/warehouse/WarehouseService.java @@ -1,8 +1,8 @@ package pl.com.bottega.factory.warehouse; import pl.com.bottega.factory.product.management.RefNoId; -import pl.com.bottega.factory.shortages.prediction.calculation.CurrentStock; +import pl.com.bottega.factory.shortages.prediction.calculation.Stock; public interface WarehouseService { - CurrentStock forRefNo(RefNoId refNo); + Stock forRefNo(RefNoId refNo); } diff --git a/app-monolith/src/main/java/pl/com/bottega/tools/CommandRepository.java b/app-monolith/src/main/java/pl/com/bottega/tools/CommandRepository.java new file mode 100644 index 0000000..a854d50 --- /dev/null +++ b/app-monolith/src/main/java/pl/com/bottega/tools/CommandRepository.java @@ -0,0 +1,27 @@ +package pl.com.bottega.tools; + +import org.springframework.data.repository.CrudRepository; +import org.springframework.data.rest.core.annotation.RestResource; +import org.springframework.stereotype.Repository; + +import java.io.Serializable; + +@Repository +public interface CommandRepository extends CrudRepository { + + @Override + @RestResource(exported = false) + void delete(ID id); + + @Override + @RestResource(exported = false) + void delete(T entity); + + @Override + @RestResource(exported = false) + void delete(Iterable entities); + + @Override + @RestResource(exported = false) + void deleteAll(); +} diff --git a/app-monolith/src/main/java/pl/com/bottega/tools/ProjectionDao.java b/app-monolith/src/main/java/pl/com/bottega/tools/ProjectionRepository.java similarity index 88% rename from app-monolith/src/main/java/pl/com/bottega/tools/ProjectionDao.java rename to app-monolith/src/main/java/pl/com/bottega/tools/ProjectionRepository.java index bd9a8ae..ec41615 100644 --- a/app-monolith/src/main/java/pl/com/bottega/tools/ProjectionDao.java +++ b/app-monolith/src/main/java/pl/com/bottega/tools/ProjectionRepository.java @@ -7,7 +7,7 @@ import org.springframework.stereotype.Repository; import java.io.Serializable; @Repository -public interface ProjectionDao extends CrudRepository { +public interface ProjectionRepository extends CrudRepository { @Override @RestResource(exported = false) diff --git a/app-monolith/src/main/resources/tasks.txt b/app-monolith/src/main/resources/tasks.txt index 78cadc1..b3152c8 100644 --- a/app-monolith/src/main/resources/tasks.txt +++ b/app-monolith/src/main/resources/tasks.txt @@ -1,4 +1,11 @@ +Aggregate Persistence: +1) normalisation of aggregate entities (Daily Demand) +2) optimistic force increment +3) mapper (Daily Demand) +4) wrapper (Product Demand) +5) event sourcing (Product Demand) + Rest: 1) crud for json document 2) query calculated @@ -9,29 +16,3 @@ Rest: 6) Eventual consistency Read your own writes (E-tag, Expect, Retry-After) - - -Aggregate Persistence: -1) optimistic force increment -2) normalisation of aggregate entities (Daily Demand) -3) mapper (Daily Demand) -4) wrapper (Product Demand) -5) event sourcing (Product Demand) - -http://pillopl.github.io/eventual-consistency-and-rest/ -https://github.com/pilloPl/orders-manager -http://groovy-lang.org/json.html - - - - - -vattenfall: - -why status is active when card is EXPIRED? -rfid: 04938C9AF74D80, point: EVB-P1552169 2 (EVB-P1552169_2) EXPIRED Revoked(authId=04938C9AF74D80, status=ACTIVE) - -exceptions: -null pointer -more results for query single card - diff --git a/app-monolith/src/test/resources/example.delivery.schema.json b/app-monolith/src/test/resources/example.delivery.schema.json deleted file mode 100644 index 7cdbcef..0000000 --- a/app-monolith/src/test/resources/example.delivery.schema.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "refNo": "3009000", - "definitions": { - "AtDayStart": { - "06:00": 1 - }, - "TillDayEnd": { - "22:00": 1 - }, - "Twice": { - "16:00": 0.5, - "20:00": 0.5 - } - } -} diff --git a/app-monolith/src/test/resources/pl.com.bottega.factory.delivery.planning/delivery-definitions.json b/app-monolith/src/test/resources/pl.com.bottega.factory.delivery.planning/delivery-definitions.json new file mode 100644 index 0000000..20e33e2 --- /dev/null +++ b/app-monolith/src/test/resources/pl.com.bottega.factory.delivery.planning/delivery-definitions.json @@ -0,0 +1,17 @@ +{ + "refNo": "3009000", + "definition": { + "definitions": { + "AtDayStart": { + "06:00": 1.0 + }, + "TillDayEnd": { + "22:00": 1.0 + }, + "Twice": { + "16:00": 0.5, + "20:00": 0.5 + } + } + } +} diff --git a/app-monolith/src/test/resources/pl.com.bottega.factory.delivery.planning/delivery-forecasts.json b/app-monolith/src/test/resources/pl.com.bottega.factory.delivery.planning/delivery-forecasts.json new file mode 100644 index 0000000..76d5f06 --- /dev/null +++ b/app-monolith/src/test/resources/pl.com.bottega.factory.delivery.planning/delivery-forecasts.json @@ -0,0 +1,6 @@ +{ + "refNo": "3009000", + "date": "2017-12-10", + "time": "2017-12-10T18:00:00.000", + "level": "3000" +} diff --git a/app-monolith/src/test/resources/pl.com.bottega.factory.demand.forecasting.command/demand-adjustments.json b/app-monolith/src/test/resources/pl.com.bottega.factory.demand.forecasting.command/demand-adjustments.json new file mode 100644 index 0000000..366df82 --- /dev/null +++ b/app-monolith/src/test/resources/pl.com.bottega.factory.demand.forecasting.command/demand-adjustments.json @@ -0,0 +1,23 @@ +{ + "note": "Customer moved demand for day earlier", + "customerRepresentative": "Krysia z logistyki", + "adjustment": { + "refNo": "3009000", + "adjustments": { + "2017-12-11": { + "demand": { + "level": 2800, + "schema": "AtDayStart" + }, + "strong": true + }, + "2017-12-12": { + "demand": { + "level": 0, + "schema": "AtDayStart" + }, + "strong": false + } + } + } +} diff --git a/app-monolith/src/test/resources/pl.com.bottega.factory.demand.forecasting.command/demand-forecasts.json b/app-monolith/src/test/resources/pl.com.bottega.factory.demand.forecasting.command/demand-forecasts.json new file mode 100644 index 0000000..aab2d7f --- /dev/null +++ b/app-monolith/src/test/resources/pl.com.bottega.factory.demand.forecasting.command/demand-forecasts.json @@ -0,0 +1,6 @@ +{ + "refNo": "3009000", + "date": "2017-12-10", + "level": "2800", + "schema": "TillDayEnd" +} diff --git a/app-monolith/src/test/resources/pl.com.bottega.factory.product.management/product-descriptions.json b/app-monolith/src/test/resources/pl.com.bottega.factory.product.management/product-descriptions.json new file mode 100644 index 0000000..7cc9d80 --- /dev/null +++ b/app-monolith/src/test/resources/pl.com.bottega.factory.product.management/product-descriptions.json @@ -0,0 +1,9 @@ +{ + "refNo": "3009000", + "description": { + "matNum": "461952398951", + "names": [ + "PROWAD.POJ.NA JARZ.ESSENT" + ] + } +} diff --git a/app-monolith/src/test/resources/pl.com.bottega.factory.production.planning/production-outputs-daily.json b/app-monolith/src/test/resources/pl.com.bottega.factory.production.planning/production-outputs-daily.json new file mode 100644 index 0000000..cb8cf8c --- /dev/null +++ b/app-monolith/src/test/resources/pl.com.bottega.factory.production.planning/production-outputs-daily.json @@ -0,0 +1,5 @@ +{ + "refNo": "3009000", + "date": "2017-12-10", + "output": "1200" +} diff --git a/app-monolith/src/test/resources/pl.com.bottega.factory.production.planning/production-outputs.json b/app-monolith/src/test/resources/pl.com.bottega.factory.production.planning/production-outputs.json new file mode 100644 index 0000000..2209a2e --- /dev/null +++ b/app-monolith/src/test/resources/pl.com.bottega.factory.production.planning/production-outputs.json @@ -0,0 +1,7 @@ +{ + "refNo": "3009000", + "start": "2017-12-10T06:15:00.000", + "duration": "DT120M", + "partsPerMinute": "10", + "total": "1200" +} diff --git a/app-monolith/src/test/resources/pl.com.bottega.factory.shortages.prediction.monitoring/shortages.json b/app-monolith/src/test/resources/pl.com.bottega.factory.shortages.prediction.monitoring/shortages.json new file mode 100644 index 0000000..839c38b --- /dev/null +++ b/app-monolith/src/test/resources/pl.com.bottega.factory.shortages.prediction.monitoring/shortages.json @@ -0,0 +1,11 @@ +{ + "refNo": "3009000", + "shortages": { + "refNo": "3009000", + "lockedParts": 0, + "found": "2017-12-10T18:21:07.293", + "shortages": { + "2018-12-11T00:00": 2800 + } + } +} diff --git a/app-monolith/src/test/resources/pl.com.bottega.factory.stock.forecast/stock-forecasts.json b/app-monolith/src/test/resources/pl.com.bottega.factory.stock.forecast/stock-forecasts.json new file mode 100644 index 0000000..36f6358 --- /dev/null +++ b/app-monolith/src/test/resources/pl.com.bottega.factory.stock.forecast/stock-forecasts.json @@ -0,0 +1,116 @@ +{ + "refNo": "3009000", + "description": { + "matNum": "461952398951", + "names": [ + "PROWAD.POJ.NA JARZ.ESSENT" + ] + }, + "forecasts": [ + { + "date": "2017-12-10", + "stock": 1200, + "withLocked": 1900, + "demand": 0, + "output": 0 + }, + { + "date": "2017-12-11", + "stock": 1200, + "withLocked": 1900, + "demand": 2800, + "output": 0 + }, + { + "date": "2017-12-12", + "stock": -1600, + "withLocked": -900, + "demand": 0, + "output": 0 + }, + { + "date": "2017-12-13", + "stock": -1600, + "withLocked": -900, + "demand": 0, + "output": 0 + }, + { + "date": "2017-12-14", + "stock": -1600, + "withLocked": -900, + "demand": 0, + "output": 0 + }, + { + "date": "2017-12-15", + "stock": -1600, + "withLocked": -900, + "demand": 0, + "output": 0 + }, + { + "date": "2017-12-16", + "stock": -1600, + "withLocked": -900, + "demand": 0, + "output": 0 + }, + { + "date": "2017-12-17", + "stock": -1600, + "withLocked": -900, + "demand": 0, + "output": 0 + }, + { + "date": "2017-12-18", + "stock": -1600, + "withLocked": -900, + "demand": 0, + "output": 0 + }, + { + "date": "2017-12-19", + "stock": -1600, + "withLocked": -900, + "demand": 0, + "output": 0 + }, + { + "date": "2017-12-20", + "stock": -1600, + "withLocked": -900, + "demand": 0, + "output": 0 + }, + { + "date": "2017-12-21", + "stock": -1600, + "withLocked": -900, + "demand": 0, + "output": 0 + }, + { + "date": "2017-12-22", + "stock": -1600, + "withLocked": -900, + "demand": 0, + "output": 0 + }, + { + "date": "2017-12-23", + "stock": -1600, + "withLocked": -900, + "demand": 0, + "output": 0 + }, + { + "date": "2017-12-24", + "stock": -1600, + "withLocked": -900, + "demand": 0, + "output": 0 + } + ] +} diff --git a/demand-forecasting-model/src/main/java/pl/com/bottega/factory/delivery/planning/DeliveriesSuggestion.java b/demand-forecasting-model/src/main/java/pl/com/bottega/factory/delivery/planning/DeliveriesSuggestion.java index eff9286..f23b86b 100644 --- a/demand-forecasting-model/src/main/java/pl/com/bottega/factory/delivery/planning/DeliveriesSuggestion.java +++ b/demand-forecasting-model/src/main/java/pl/com/bottega/factory/delivery/planning/DeliveriesSuggestion.java @@ -15,10 +15,10 @@ interface DeliveriesSuggestion { static DeliveriesSuggestion timesAndFractions(Map timesAndFractions) { return (refNo, date, demand) -> timesAndFractions.entrySet().stream() - .map(e -> new Delivery( - refNo, - date.atTime(e.getKey()), ((long)((double)demand.getLevel() / e.getValue()))) - ); + .map(e -> new Delivery( + refNo, + date.atTime(e.getKey()), ((long) ((double) demand.getLevel() / e.getValue()))) + ); } Stream deliveriesFor(String refNo, LocalDate date, Demand demand); diff --git a/demand-forecasting-model/src/main/java/pl/com/bottega/factory/delivery/planning/DeliveryAutoPlanner.java b/demand-forecasting-model/src/main/java/pl/com/bottega/factory/delivery/planning/DeliveryAutoPlanner.java index b78fb52..96a1c0e 100644 --- a/demand-forecasting-model/src/main/java/pl/com/bottega/factory/delivery/planning/DeliveryAutoPlanner.java +++ b/demand-forecasting-model/src/main/java/pl/com/bottega/factory/delivery/planning/DeliveryAutoPlanner.java @@ -1,7 +1,7 @@ package pl.com.bottega.factory.delivery.planning; -import pl.com.bottega.factory.demand.forecasting.Demand; import lombok.AllArgsConstructor; +import pl.com.bottega.factory.demand.forecasting.Demand; import java.time.LocalDate; import java.util.Map; diff --git a/demand-forecasting-model/src/main/java/pl/com/bottega/factory/demand/forecasting/AdjustDemand.java b/demand-forecasting-model/src/main/java/pl/com/bottega/factory/demand/forecasting/AdjustDemand.java index a23fa25..353d706 100644 --- a/demand-forecasting-model/src/main/java/pl/com/bottega/factory/demand/forecasting/AdjustDemand.java +++ b/demand-forecasting-model/src/main/java/pl/com/bottega/factory/demand/forecasting/AdjustDemand.java @@ -3,8 +3,9 @@ package pl.com.bottega.factory.demand.forecasting; import lombok.Value; import java.time.LocalDate; -import java.util.Collections; +import java.util.Comparator; import java.util.Map; +import java.util.Optional; import java.util.function.BiConsumer; @Value @@ -12,15 +13,13 @@ public class AdjustDemand { String refNo; Map adjustments; - public AdjustDemand(String refNo, - Map adjustments) { - this.refNo = refNo; - this.adjustments = Collections.unmodifiableMap(adjustments); - } - public void forEachStartingFrom(LocalDate date, BiConsumer f) { adjustments.entrySet().stream() .filter(e -> !e.getKey().isBefore(date)) .forEach(e -> f.accept(e.getKey(), e.getValue())); } + + public Optional latestAdjustment() { + return adjustments.keySet().stream().max(Comparator.naturalOrder()); + } } diff --git a/shortages-prediction-model/src/main/java/pl/com/bottega/factory/shortages/prediction/calculation/Forecast.java b/shortages-prediction-model/src/main/java/pl/com/bottega/factory/shortages/prediction/calculation/Forecast.java index e0bc1da..53781f8 100644 --- a/shortages-prediction-model/src/main/java/pl/com/bottega/factory/shortages/prediction/calculation/Forecast.java +++ b/shortages-prediction-model/src/main/java/pl/com/bottega/factory/shortages/prediction/calculation/Forecast.java @@ -4,25 +4,25 @@ import lombok.AllArgsConstructor; import pl.com.bottega.factory.shortages.prediction.Shortages; import java.time.LocalDateTime; -import java.util.List; import java.util.Optional; +import java.util.SortedSet; @AllArgsConstructor public class Forecast { - String refNo; - LocalDateTime created; - List times; - CurrentStock stock; - ProductionOutputs outputs; - Demands demands; + private final String refNo; + private final LocalDateTime created; + private final SortedSet deliveryTimes; + private final Stock stock; + private final ProductionOutputs outputs; + private final Demands demands; public Optional findShortages() { long level = stock.getLevel(); Shortages.Builder found = Shortages.builder(refNo, stock.getLocked(), created); LocalDateTime lastTime = created; - for (LocalDateTime time : times) { + for (LocalDateTime time : deliveryTimes) { long demand = demands.get(time); long produced = outputs.getOutput(lastTime, time); diff --git a/shortages-prediction-model/src/main/java/pl/com/bottega/factory/shortages/prediction/calculation/CurrentStock.java b/shortages-prediction-model/src/main/java/pl/com/bottega/factory/shortages/prediction/calculation/Stock.java similarity index 82% rename from shortages-prediction-model/src/main/java/pl/com/bottega/factory/shortages/prediction/calculation/CurrentStock.java rename to shortages-prediction-model/src/main/java/pl/com/bottega/factory/shortages/prediction/calculation/Stock.java index fa1efcc..c41dc58 100644 --- a/shortages-prediction-model/src/main/java/pl/com/bottega/factory/shortages/prediction/calculation/CurrentStock.java +++ b/shortages-prediction-model/src/main/java/pl/com/bottega/factory/shortages/prediction/calculation/Stock.java @@ -3,7 +3,7 @@ package pl.com.bottega.factory.shortages.prediction.calculation; import lombok.Value; @Value -public class CurrentStock { +public class Stock { long level; long locked; } diff --git a/shortages-prediction-model/src/test/groovy/pl/com/bottega/factory/shortages/prediction/calculation/ShortagesCalculationAssemblerTrait.groovy b/shortages-prediction-model/src/test/groovy/pl/com/bottega/factory/shortages/prediction/calculation/ShortagesCalculationAssemblerTrait.groovy index 4f6e569..c91b0cc 100644 --- a/shortages-prediction-model/src/test/groovy/pl/com/bottega/factory/shortages/prediction/calculation/ShortagesCalculationAssemblerTrait.groovy +++ b/shortages-prediction-model/src/test/groovy/pl/com/bottega/factory/shortages/prediction/calculation/ShortagesCalculationAssemblerTrait.groovy @@ -12,12 +12,12 @@ trait ShortagesCalculationAssemblerTrait { String refNo = "3009000" Set times - Forecasts forecastProvider(CurrentStock stock, Demands demands, ProductionOutputs outputs) { + Forecasts forecastProvider(Stock stock, Demands demands, ProductionOutputs outputs) { def forecast = forecast(stock, demands, outputs) return { RefNoId refNo, int daysAhead -> forecast } as Forecasts } - Forecast forecast(CurrentStock stock, Demands demands, ProductionOutputs outputs) { + Forecast forecast(Stock stock, Demands demands, ProductionOutputs outputs) { new Forecast(refNo, now, times as List, stock, outputs, demands) } @@ -45,12 +45,12 @@ trait ShortagesCalculationAssemblerTrait { new Demands(demands) } - CurrentStock stock(long levels) { - new CurrentStock(levels, 0) + Stock stock(long levels) { + new Stock(levels, 0) } - CurrentStock stock(long level, long locked) { - new CurrentStock(level, locked) + Stock stock(long level, long locked) { + new Stock(level, locked) } Optional noShortages() {