modular database schema
This commit is contained in:
@@ -19,6 +19,7 @@ public abstract class JsonConverter<T> implements AttributeConverter<T, String>
|
||||
.setVisibility(PropertyAccessor.CREATOR, JsonAutoDetect.Visibility.ANY)
|
||||
.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
|
||||
.enable(SerializationFeature.WRITE_DATES_WITH_ZONE_ID)
|
||||
.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS)
|
||||
.registerModule(new JavaTimeModule());
|
||||
|
||||
private final Class<T> type;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
spring.main.banner-mode=off
|
||||
spring.jpa.database=default
|
||||
spring.jpa.generate-ddl=true
|
||||
spring.jpa.generate-ddl=false
|
||||
spring.datasource.url=jdbc:postgresql://localhost:5432/postgres
|
||||
spring.datasource.username=postgres
|
||||
spring.datasource.password=
|
||||
|
||||
@@ -1,19 +1,14 @@
|
||||
package pl.com.bottega.factory.stock.forecast.ressource;
|
||||
|
||||
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.ProjectionRepository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Repository
|
||||
@RepositoryRestResource(path = "stock-forecasts",
|
||||
collectionResourceRel = "stock-forecasts",
|
||||
itemResourceRel = "stock-forecast",
|
||||
excerptProjection = StockForecastEntity.CollectionItem.class)
|
||||
public interface StockForecastDao extends ProjectionRepository<StockForecastEntity, Long> {
|
||||
public interface StockForecastDao extends ProjectionRepository<StockForecastEntity, String> {
|
||||
|
||||
@RestResource(path = "refNos", rel = "refNos")
|
||||
List<StockForecastEntity> findByProductRefNo(String refNo);
|
||||
}
|
||||
|
||||
@@ -1,27 +1,22 @@
|
||||
package pl.com.bottega.factory.stock.forecast.ressource;
|
||||
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.ToString;
|
||||
import org.springframework.data.rest.core.config.Projection;
|
||||
import pl.com.bottega.factory.stock.forecast.StockForecast;
|
||||
|
||||
import javax.persistence.*;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
import java.io.Serializable;
|
||||
|
||||
@Entity(name = "StockForecast")
|
||||
@Table(schema = "shortages_prediction")
|
||||
@Getter
|
||||
@NoArgsConstructor
|
||||
@EqualsAndHashCode(of = "id")
|
||||
@ToString
|
||||
public class StockForecastEntity implements Serializable {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||
private Long id;
|
||||
|
||||
@Column
|
||||
private String refNo;
|
||||
|
||||
public StockForecastEntity(String refNo) {
|
||||
|
||||
@@ -5,6 +5,8 @@ curl -X POST -H "Content-Type: application/json" \
|
||||
-d @app-monolith/src/test/resources/examples/product-descriptions.json \
|
||||
http://localhost:8080/product-descriptions
|
||||
|
||||
curl http://localhost:8080/stock-forecasts
|
||||
|
||||
curl -X POST -H "Content-Type: application/json" \
|
||||
-d @app-monolith/src/test/resources/examples/delivery-definitions.json \
|
||||
http://localhost:8080/delivery-definitions
|
||||
|
||||
@@ -1,4 +1,2 @@
|
||||
|
||||
--create schema demands authorization postgres;
|
||||
--create schema shortages authorization postgres;
|
||||
--create schema products authorization postgres;
|
||||
-- see schema directory
|
||||
|
||||
12
database/schema/commons.sql
Normal file
12
database/schema/commons.sql
Normal file
@@ -0,0 +1,12 @@
|
||||
--liquibase formatted sql
|
||||
|
||||
--changeset michaluk.michal:1.init
|
||||
|
||||
CREATE SEQUENCE hibernate_sequence
|
||||
START WITH 1
|
||||
INCREMENT BY 1
|
||||
NO MINVALUE
|
||||
NO MAXVALUE
|
||||
CACHE 1;
|
||||
|
||||
CREATE CAST (character varying AS json) WITH INOUT AS ASSIGNMENT;
|
||||
@@ -2,7 +2,10 @@
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.4.xsd">
|
||||
<!--<include file="/schema/product-management.sql"/>-->
|
||||
<!--<include file="/schema/demand-forecasting.sql"/>-->
|
||||
<!--<include file="/schema/shortages-prediction.sql"/>-->
|
||||
<include file="/schema/commons.sql"/>
|
||||
<include file="/schema/delivery-planning.sql"/>
|
||||
<include file="/schema/demand-forecasting.sql"/>
|
||||
<include file="/schema/product-management.sql"/>
|
||||
<include file="/schema/production-planning.sql"/>
|
||||
<include file="/schema/shortages-prediction.sql"/>
|
||||
</databaseChangeLog>
|
||||
|
||||
17
database/schema/delivery-planning.sql
Normal file
17
database/schema/delivery-planning.sql
Normal file
@@ -0,0 +1,17 @@
|
||||
--liquibase formatted sql
|
||||
|
||||
--changeset michaluk.michal:1.init
|
||||
CREATE SCHEMA delivery_planning;
|
||||
|
||||
CREATE TABLE delivery_planning.delivery_planner_definition (
|
||||
ref_no character varying(64) NOT NULL PRIMARY KEY,
|
||||
definition json NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE delivery_planning.delivery_forecast (
|
||||
id serial NOT NULL PRIMARY KEY,
|
||||
ref_no character varying(64) NOT NULL,
|
||||
"time" timestamp without time zone NOT NULL,
|
||||
"date" timestamp without time zone NOT NULL,
|
||||
level bigint NOT NULL
|
||||
);
|
||||
46
database/schema/demand-forecasting.sql
Normal file
46
database/schema/demand-forecasting.sql
Normal file
@@ -0,0 +1,46 @@
|
||||
--liquibase formatted sql
|
||||
|
||||
--changeset michaluk.michal:1.init
|
||||
CREATE SCHEMA demand_forecasting;
|
||||
|
||||
CREATE TABLE demand_forecasting.product_demand (
|
||||
id serial NOT NULL PRIMARY KEY,
|
||||
version bigint NOT NULL,
|
||||
ref_no character varying(64) NOT NULL,
|
||||
UNIQUE(ref_no)
|
||||
);
|
||||
|
||||
CREATE TABLE demand_forecasting."demand" (
|
||||
id serial NOT NULL PRIMARY KEY,
|
||||
ref_no character varying(64) NOT NULL,
|
||||
"date" timestamp without time zone NOT NULL,
|
||||
value json NOT NULL,
|
||||
UNIQUE(ref_no, "date")
|
||||
);
|
||||
|
||||
CREATE TABLE demand_forecasting.current_demand (
|
||||
id serial NOT NULL PRIMARY KEY,
|
||||
ref_no character varying(64) NOT NULL,
|
||||
"date" timestamp without time zone NOT NULL,
|
||||
level bigint NOT NULL,
|
||||
"schema" character varying(64) NOT NULL,
|
||||
UNIQUE(ref_no, "date")
|
||||
);
|
||||
|
||||
CREATE TABLE demand_forecasting.demand_adjustment (
|
||||
id serial NOT NULL PRIMARY KEY,
|
||||
customer_representative character varying(255) NOT NULL,
|
||||
note character varying(255) NOT NULL,
|
||||
adjustment json NOT NULL,
|
||||
clean_after timestamp without time zone
|
||||
);
|
||||
|
||||
CREATE TABLE demand_forecasting.demand_review (
|
||||
id serial NOT NULL PRIMARY KEY,
|
||||
ref_no character varying(64) NOT NULL,
|
||||
"date" timestamp without time zone NOT NULL,
|
||||
"timestamp" timestamp without time zone NOT NULL,
|
||||
review json NOT NULL,
|
||||
decision character varying(64),
|
||||
clean_after timestamp without time zone
|
||||
);
|
||||
@@ -1,3 +1,9 @@
|
||||
--liquibase formatted sql
|
||||
|
||||
--changeset michaluk.michal:1.init
|
||||
CREATE SCHEMA product_management;
|
||||
|
||||
CREATE TABLE product_management.product_description (
|
||||
ref_no character varying(64) NOT NULL PRIMARY KEY,
|
||||
description json NOT NULL
|
||||
);
|
||||
|
||||
22
database/schema/production-planning.sql
Normal file
22
database/schema/production-planning.sql
Normal file
@@ -0,0 +1,22 @@
|
||||
--liquibase formatted sql
|
||||
|
||||
--changeset michaluk.michal:1.init
|
||||
CREATE SCHEMA production_planning;
|
||||
|
||||
CREATE TABLE production_planning.production_daily_output (
|
||||
id serial NOT NULL PRIMARY KEY,
|
||||
ref_no character varying(64) NOT NULL,
|
||||
"date" timestamp without time zone NOT NULL,
|
||||
output bigint NOT NULL,
|
||||
UNIQUE(ref_no, "date")
|
||||
);
|
||||
|
||||
CREATE TABLE production_planning.production_output (
|
||||
id serial NOT NULL PRIMARY KEY,
|
||||
ref_no character varying(64) NOT NULL,
|
||||
"start" timestamp without time zone NOT NULL,
|
||||
"end" timestamp without time zone NOT NULL,
|
||||
duration bigint NOT NULL,
|
||||
parts_per_minute integer NOT NULL,
|
||||
total bigint NOT NULL
|
||||
);
|
||||
16
database/schema/shortages-prediction.sql
Normal file
16
database/schema/shortages-prediction.sql
Normal file
@@ -0,0 +1,16 @@
|
||||
--liquibase formatted sql
|
||||
|
||||
--changeset michaluk.michal:1.init
|
||||
CREATE SCHEMA shortages_prediction;
|
||||
|
||||
CREATE TABLE shortages_prediction.shortage (
|
||||
id serial NOT NULL PRIMARY KEY,
|
||||
version bigint NOT NULL,
|
||||
ref_no character varying(64) NOT NULL,
|
||||
shortages json NOT NULL,
|
||||
UNIQUE(ref_no)
|
||||
);
|
||||
|
||||
CREATE TABLE shortages_prediction.stock_forecast (
|
||||
ref_no character varying(64) NOT NULL PRIMARY KEY
|
||||
);
|
||||
@@ -25,6 +25,13 @@
|
||||
<artifactId>adapter-commons</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>pl.com.bottega</groupId>
|
||||
<artifactId>adapter-commons</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<type>test-jar</type>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
|
||||
@@ -17,7 +17,7 @@ public class DeliveryAutoPlannerORMRepository {
|
||||
|
||||
public DeliveryAutoPlanner get(String refNo) {
|
||||
return new DeliveryAutoPlanner(refNo,
|
||||
ofNullable(dao.findByRefNo(refNo))
|
||||
ofNullable(dao.findOne(refNo))
|
||||
.map(DeliveryPlannerDefinitionEntity::getDefinition)
|
||||
.map(x -> x.map(DeliveriesSuggestion::timesAndFractions))
|
||||
.orElse(Collections.emptyMap()));
|
||||
|
||||
@@ -2,8 +2,8 @@ package pl.com.bottega.factory.delivery.planning.definition;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Singular;
|
||||
import lombok.Value;
|
||||
import pl.com.bottega.factory.demand.forecasting.Demand;
|
||||
|
||||
import java.time.LocalTime;
|
||||
@@ -13,8 +13,8 @@ import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Builder
|
||||
@Value
|
||||
@AllArgsConstructor
|
||||
@EqualsAndHashCode
|
||||
public class DeliveryPlannerDefinition {
|
||||
@Singular
|
||||
private final Map<Demand.Schema, Map<LocalTime, Double>> definitions;
|
||||
|
||||
@@ -2,7 +2,6 @@ package pl.com.bottega.factory.delivery.planning.definition;
|
||||
|
||||
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;
|
||||
|
||||
@Repository
|
||||
@@ -10,7 +9,6 @@ import org.springframework.stereotype.Repository;
|
||||
path = "delivery-definitions",
|
||||
collectionResourceRel = "delivery-definitions",
|
||||
itemResourceRel = "delivery-definition")
|
||||
public interface DeliveryPlannerDefinitionDao extends JpaRepository<DeliveryPlannerDefinitionEntity, Long> {
|
||||
@RestResource(path = "refNos", rel = "refNos")
|
||||
DeliveryPlannerDefinitionEntity findByRefNo(String refNo);
|
||||
public interface DeliveryPlannerDefinitionDao extends JpaRepository<DeliveryPlannerDefinitionEntity, String> {
|
||||
|
||||
}
|
||||
|
||||
@@ -1,26 +1,24 @@
|
||||
package pl.com.bottega.factory.delivery.planning.definition;
|
||||
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import pl.com.bottega.tools.JsonConverter;
|
||||
|
||||
import javax.persistence.*;
|
||||
import javax.persistence.Convert;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
import java.io.Serializable;
|
||||
|
||||
@Entity(name = "DeliveryPlannerDefinition")
|
||||
@Table(schema = "delivery_planning")
|
||||
@Getter
|
||||
@NoArgsConstructor
|
||||
@EqualsAndHashCode(of = "refNo")
|
||||
public class DeliveryPlannerDefinitionEntity implements Serializable {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||
private Long id;
|
||||
@Column
|
||||
private String refNo;
|
||||
@Column
|
||||
@Convert(converter = DescriptionAsJson.class)
|
||||
@Convert(converter = DefinitionAsJson.class)
|
||||
private DeliveryPlannerDefinition definition;
|
||||
|
||||
public DeliveryPlannerDefinitionEntity(String refNo, DeliveryPlannerDefinition definition) {
|
||||
@@ -28,8 +26,8 @@ public class DeliveryPlannerDefinitionEntity implements Serializable {
|
||||
this.definition = definition;
|
||||
}
|
||||
|
||||
public static class DescriptionAsJson extends JsonConverter<DeliveryPlannerDefinition> {
|
||||
public DescriptionAsJson() {
|
||||
public static class DefinitionAsJson extends JsonConverter<DeliveryPlannerDefinition> {
|
||||
public DefinitionAsJson() {
|
||||
super(DeliveryPlannerDefinition.class);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,30 +1,28 @@
|
||||
package pl.com.bottega.factory.delivery.planning.projection;
|
||||
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import javax.persistence.*;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Entity(name = "DeliveryForecast")
|
||||
@Table(schema = "delivery_planning")
|
||||
@Getter
|
||||
@NoArgsConstructor
|
||||
@EqualsAndHashCode(of = {"refNo", "date"})
|
||||
public class DeliveryForecastEntity implements Serializable {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||
@GeneratedValue
|
||||
private Long id;
|
||||
@Column
|
||||
private String refNo;
|
||||
@Column
|
||||
private LocalDate date;
|
||||
@Column
|
||||
private LocalDateTime time;
|
||||
@Column
|
||||
private long level;
|
||||
|
||||
DeliveryForecastEntity(String refNo, LocalDateTime time, long level) {
|
||||
|
||||
@@ -37,7 +37,7 @@ class DemandORMRepository {
|
||||
RefNoId id = root.createId();
|
||||
|
||||
Map<LocalDate, DemandEntity> data =
|
||||
demandDao.findByProductRefNoAndDateGreaterThanEqual(refNo, LocalDate.now(clock)).stream()
|
||||
demandDao.findByRefNoAndDateGreaterThanEqual(refNo, LocalDate.now(clock)).stream()
|
||||
.collect(toMap(
|
||||
DemandEntity::getDate,
|
||||
Function.identity()
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package pl.com.bottega.factory.demand.forecasting.command;
|
||||
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
@@ -12,27 +11,22 @@ import java.io.Serializable;
|
||||
import java.time.LocalDate;
|
||||
|
||||
@Entity(name = "DemandAdjustment")
|
||||
@Table(schema = "demand_forecasting")
|
||||
@Getter
|
||||
@NoArgsConstructor
|
||||
@EqualsAndHashCode(of = "id")
|
||||
public class DemandAdjustmentEntity implements Serializable {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||
@GeneratedValue
|
||||
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;
|
||||
|
||||
@Setter
|
||||
private LocalDate cleanAfter;
|
||||
|
||||
public static class AdjustDemandAsJson extends JsonConverter<AdjustDemand> {
|
||||
public AdjustDemandAsJson() {
|
||||
super(AdjustDemand.class);
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package pl.com.bottega.factory.demand.forecasting.command;
|
||||
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
@@ -14,29 +13,22 @@ import java.time.Instant;
|
||||
import java.time.LocalDate;
|
||||
|
||||
@Entity(name = "DemandReview")
|
||||
@Table(schema = "demand_forecasting")
|
||||
@Getter
|
||||
@NoArgsConstructor
|
||||
@EqualsAndHashCode(of = "id")
|
||||
public class DemandReviewEntity implements Serializable {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||
@GeneratedValue
|
||||
private Long id;
|
||||
|
||||
@Column
|
||||
private String refNo;
|
||||
@Column
|
||||
private LocalDate date;
|
||||
@Column
|
||||
private Instant timestamp;
|
||||
@Column
|
||||
@Convert(converter = ReviewAsJson.class)
|
||||
private ReviewNeeded review;
|
||||
|
||||
@Column
|
||||
@Enumerated(EnumType.STRING)
|
||||
private ReviewDecision decision;
|
||||
@Column
|
||||
@Setter
|
||||
private LocalDate cleanAfter;
|
||||
|
||||
|
||||
@@ -10,5 +10,5 @@ import java.util.List;
|
||||
@Repository
|
||||
@RestResource(exported = false)
|
||||
public interface DemandDao extends JpaRepository<DemandEntity, Long> {
|
||||
List<DemandEntity> findByProductRefNoAndDateGreaterThanEqual(String refNo, LocalDate now);
|
||||
List<DemandEntity> findByRefNoAndDateGreaterThanEqual(String refNo, LocalDate now);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package pl.com.bottega.factory.demand.forecasting.persistence;
|
||||
|
||||
import lombok.*;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import pl.com.bottega.factory.demand.forecasting.DailyId;
|
||||
import pl.com.bottega.factory.demand.forecasting.DemandValue;
|
||||
import pl.com.bottega.tools.JsonConverter;
|
||||
@@ -11,22 +13,18 @@ import java.io.Serializable;
|
||||
import java.time.LocalDate;
|
||||
|
||||
@Entity(name = "Demand")
|
||||
@Table(schema = "demand_forecasting")
|
||||
@Getter
|
||||
@NoArgsConstructor
|
||||
@EqualsAndHashCode(of = "id")
|
||||
@ToString
|
||||
public class DemandEntity implements Serializable {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||
@GeneratedValue
|
||||
private Long id;
|
||||
@Column
|
||||
String refNo;
|
||||
@Column
|
||||
private String refNo;
|
||||
private LocalDate date;
|
||||
@Column
|
||||
@Convert(converter = DemandAsJson.class)
|
||||
@Setter
|
||||
@Convert(converter = DemandAsJson.class)
|
||||
private DemandValue value;
|
||||
|
||||
public DemandEntity(String refNo, LocalDate date) {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package pl.com.bottega.factory.demand.forecasting.persistence;
|
||||
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import pl.com.bottega.factory.product.management.RefNoId;
|
||||
@@ -10,17 +9,16 @@ import javax.persistence.*;
|
||||
import java.io.Serializable;
|
||||
|
||||
@Entity(name = "ProductDemand")
|
||||
@Table(schema = "demand_forecasting")
|
||||
@NoArgsConstructor
|
||||
@EqualsAndHashCode(of = "id")
|
||||
public class ProductDemandEntity implements Serializable {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||
@GeneratedValue
|
||||
private Long id;
|
||||
@Version
|
||||
private Long version;
|
||||
@Column
|
||||
String refNo;
|
||||
private String refNo;
|
||||
|
||||
public ProductDemandEntity(String refNo) {
|
||||
this.refNo = refNo;
|
||||
@@ -33,11 +31,7 @@ public class ProductDemandEntity implements Serializable {
|
||||
@Getter
|
||||
static class ProductDemandEntityId extends RefNoId implements TechnicalId {
|
||||
|
||||
Long id;
|
||||
|
||||
ProductDemandEntityId(String refNo) {
|
||||
super(refNo);
|
||||
}
|
||||
private Long id;
|
||||
|
||||
ProductDemandEntityId(String refNo, long id) {
|
||||
super(refNo);
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package pl.com.bottega.factory.demand.forecasting.projection;
|
||||
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import pl.com.bottega.factory.demand.forecasting.Demand;
|
||||
@@ -10,21 +9,17 @@ import java.io.Serializable;
|
||||
import java.time.LocalDate;
|
||||
|
||||
@Entity(name = "CurrentDemand")
|
||||
@Table(schema = "demand_forecasting")
|
||||
@Getter
|
||||
@NoArgsConstructor
|
||||
@EqualsAndHashCode(of = "id")
|
||||
public class CurrentDemandEntity implements Serializable {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||
@GeneratedValue
|
||||
private Long id;
|
||||
@Column
|
||||
private String refNo;
|
||||
@Column
|
||||
private LocalDate date;
|
||||
@Column
|
||||
private long level;
|
||||
@Column
|
||||
@Enumerated(EnumType.STRING)
|
||||
private Demand.Schema schema;
|
||||
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
package pl.com.bottega.factory;
|
||||
|
||||
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 org.springframework.scheduling.annotation.EnableScheduling;
|
||||
import pl.com.bottega.factory.demand.forecasting.DemandEvents;
|
||||
import pl.com.bottega.factory.demand.forecasting.DemandedLevelsChanged;
|
||||
import pl.com.bottega.factory.demand.forecasting.ReviewRequested;
|
||||
|
||||
import java.time.Clock;
|
||||
|
||||
@SpringBootApplication
|
||||
@EnableScheduling
|
||||
@EntityScan(
|
||||
basePackageClasses = {Configuration.class, Jsr310JpaConverters.class}
|
||||
)
|
||||
public class Configuration {
|
||||
@Bean
|
||||
public Clock clock() {
|
||||
return Clock.systemDefaultZone();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public DemandEventsFake DemandEvents() {
|
||||
return new DemandEventsFake();
|
||||
}
|
||||
|
||||
private class DemandEventsFake implements DemandEvents {
|
||||
@Override
|
||||
public void emit(DemandedLevelsChanged event) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void emit(ReviewRequested event) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -76,7 +76,7 @@ class DemandORMRepositoryTest extends Specification {
|
||||
demandInDB((today.minusDays(1)): 10000, (today): 1000)
|
||||
|
||||
when:
|
||||
def demands = demandDao.findByProductRefNoAndDateGreaterThanEqual(refNo, today)
|
||||
def demands = demandDao.findByRefNoAndDateGreaterThanEqual(refNo, today)
|
||||
|
||||
then:
|
||||
demands.size() == 1
|
||||
@@ -90,7 +90,7 @@ class DemandORMRepositoryTest extends Specification {
|
||||
private void demandInDB(Map<LocalDate, Long> demands) {
|
||||
def root = rootDao.save(new ProductDemandEntity(refNo))
|
||||
demands.each { date, level ->
|
||||
def demand = new DemandEntity(root, date)
|
||||
def demand = new DemandEntity(refNo, date)
|
||||
demand.setValue(new DemandValue(Demand.of(level), null))
|
||||
demandDao.save(demand)
|
||||
}
|
||||
@@ -107,6 +107,6 @@ class DemandORMRepositoryTest extends Specification {
|
||||
}
|
||||
|
||||
private def hasAdjustment(long level) {
|
||||
return { it.get().getAdjustment() == Adjustment.strong(Demand.of(level)) }
|
||||
return { it.getValue().getAdjustment() == Adjustment.strong(Demand.of(level)) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,13 @@
|
||||
<artifactId>adapter-commons</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>pl.com.bottega</groupId>
|
||||
<artifactId>adapter-commons</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<type>test-jar</type>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
|
||||
@@ -2,7 +2,6 @@ package pl.com.bottega.factory.product.management;
|
||||
|
||||
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;
|
||||
|
||||
@Repository
|
||||
@@ -10,7 +9,6 @@ import org.springframework.stereotype.Repository;
|
||||
path = "product-descriptions",
|
||||
collectionResourceRel = "product-descriptions",
|
||||
itemResourceRel = "product-description")
|
||||
public interface ProductDescriptionDao extends JpaRepository<ProductDescriptionEntity, Long> {
|
||||
@RestResource(path = "refNos", rel = "refNos")
|
||||
ProductDescriptionEntity findByRefNo(String refNo);
|
||||
public interface ProductDescriptionDao extends JpaRepository<ProductDescriptionEntity, String> {
|
||||
|
||||
}
|
||||
|
||||
@@ -1,29 +1,27 @@
|
||||
package pl.com.bottega.factory.product.management;
|
||||
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import pl.com.bottega.tools.JsonConverter;
|
||||
|
||||
import javax.persistence.*;
|
||||
import javax.persistence.Convert;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
import java.io.Serializable;
|
||||
|
||||
@Entity(name = "ProductDescription")
|
||||
@Table(schema = "product_management")
|
||||
@Getter
|
||||
@NoArgsConstructor
|
||||
@EqualsAndHashCode(of = "refNo")
|
||||
public class ProductDescriptionEntity implements Serializable {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||
private Long id;
|
||||
@Column
|
||||
private String refNo;
|
||||
@Column
|
||||
@Convert(converter = DescriptionAsJson.class)
|
||||
ProductDescription description;
|
||||
private ProductDescription description;
|
||||
|
||||
public ProductDescriptionEntity(String refNo, ProductDescription description) {
|
||||
ProductDescriptionEntity(String refNo, ProductDescription description) {
|
||||
this.refNo = refNo;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
package pl.com.bottega.factory;
|
||||
|
||||
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 org.springframework.scheduling.annotation.EnableScheduling;
|
||||
|
||||
import java.time.Clock;
|
||||
|
||||
@SpringBootApplication
|
||||
@EnableScheduling
|
||||
@EntityScan(
|
||||
basePackageClasses = {Configuration.class, Jsr310JpaConverters.class}
|
||||
)
|
||||
public class Configuration {
|
||||
@Bean
|
||||
public Clock clock() {
|
||||
return Clock.systemDefaultZone();
|
||||
}
|
||||
}
|
||||
@@ -20,6 +20,13 @@
|
||||
<artifactId>adapter-commons</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>pl.com.bottega</groupId>
|
||||
<artifactId>adapter-commons</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<type>test-jar</type>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
|
||||
@@ -1,30 +1,29 @@
|
||||
package pl.com.bottega.factory.production.planning.projection;
|
||||
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import javax.persistence.*;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDate;
|
||||
|
||||
@Entity(name = "ProductionDailyOutput")
|
||||
@Table(schema = "production_planning")
|
||||
@Getter
|
||||
@NoArgsConstructor
|
||||
@EqualsAndHashCode(of = "refNo")
|
||||
public class ProductionDailyOutputEntity implements Serializable {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||
@GeneratedValue
|
||||
private Long id;
|
||||
@Column
|
||||
private String refNo;
|
||||
@Column
|
||||
private LocalDate date;
|
||||
@Column
|
||||
private long output;
|
||||
|
||||
public ProductionDailyOutputEntity(String refNo, LocalDate date, long output) {
|
||||
ProductionDailyOutputEntity(String refNo, LocalDate date, long output) {
|
||||
this.refNo = refNo;
|
||||
this.date = date;
|
||||
this.output = output;
|
||||
|
||||
@@ -1,45 +1,45 @@
|
||||
package pl.com.bottega.factory.production.planning.projection;
|
||||
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import javax.persistence.*;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
import java.io.Serializable;
|
||||
import java.time.Duration;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Entity(name = "ProductionOutput")
|
||||
@Table(schema = "production_planning")
|
||||
@Getter
|
||||
@NoArgsConstructor
|
||||
@EqualsAndHashCode(of = "refNo")
|
||||
public class ProductionOutputEntity implements Serializable {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||
@GeneratedValue
|
||||
private Long id;
|
||||
@Column
|
||||
private String refNo;
|
||||
@Column
|
||||
private LocalDateTime start;
|
||||
@Column
|
||||
private Duration duration;
|
||||
@Column
|
||||
private long duration;
|
||||
private LocalDateTime end;
|
||||
@Column
|
||||
private int partsPerMinute;
|
||||
@Column
|
||||
private long total;
|
||||
|
||||
public ProductionOutputEntity(String refNo,
|
||||
LocalDateTime start, Duration duration,
|
||||
int partsPerMinute,
|
||||
long total) {
|
||||
ProductionOutputEntity(String refNo,
|
||||
LocalDateTime start, Duration duration,
|
||||
int partsPerMinute,
|
||||
long total) {
|
||||
this.refNo = refNo;
|
||||
this.start = start;
|
||||
this.duration = duration;
|
||||
this.duration = duration.getSeconds();
|
||||
this.end = start.plus(duration);
|
||||
this.partsPerMinute = partsPerMinute;
|
||||
this.total = total;
|
||||
}
|
||||
|
||||
public Duration getDuration() {
|
||||
return Duration.ofSeconds(duration);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,13 @@
|
||||
<artifactId>adapter-commons</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>pl.com.bottega</groupId>
|
||||
<artifactId>adapter-commons</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<type>test-jar</type>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
|
||||
@@ -14,4 +14,6 @@ import java.util.Optional;
|
||||
public interface ShortagesDao extends ProjectionRepository<ShortagesEntity, Long> {
|
||||
@RestResource(path = "refNos", rel = "refNos")
|
||||
Optional<ShortagesEntity> findByRefNo(String refNo);
|
||||
|
||||
void deleteAllInBatch();
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package pl.com.bottega.factory.shortages.prediction.monitoring.persistence;
|
||||
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
@@ -13,21 +12,19 @@ import javax.persistence.*;
|
||||
import java.io.Serializable;
|
||||
|
||||
@Entity(name = "Shortage")
|
||||
@Table(schema = "shortages_prediction")
|
||||
@Getter
|
||||
@NoArgsConstructor
|
||||
@EqualsAndHashCode(of = "refNo")
|
||||
public class ShortagesEntity implements Serializable {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||
@GeneratedValue
|
||||
private Long id;
|
||||
@Version
|
||||
private Long version;
|
||||
@Column
|
||||
private String refNo;
|
||||
@Column(length = 1024)
|
||||
@Convert(converter = ShortagesAsJson.class)
|
||||
@Setter
|
||||
@Convert(converter = ShortagesAsJson.class)
|
||||
private Shortages shortages;
|
||||
|
||||
public ShortagesEntity(String refNo) {
|
||||
@@ -51,7 +48,7 @@ public class ShortagesEntity implements Serializable {
|
||||
@Getter
|
||||
static class ShortagesEntityId extends RefNoId implements TechnicalId {
|
||||
|
||||
Long id;
|
||||
private Long id;
|
||||
|
||||
ShortagesEntityId(String refNo) {
|
||||
super(refNo);
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
package pl.com.bottega.factory;
|
||||
|
||||
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 org.springframework.scheduling.annotation.EnableScheduling;
|
||||
import pl.com.bottega.factory.product.management.RefNoId;
|
||||
import pl.com.bottega.factory.shortages.prediction.calculation.Forecast;
|
||||
import pl.com.bottega.factory.shortages.prediction.calculation.Forecasts;
|
||||
import pl.com.bottega.factory.shortages.prediction.monitoring.NewShortage;
|
||||
import pl.com.bottega.factory.shortages.prediction.monitoring.ShortageEvents;
|
||||
import pl.com.bottega.factory.shortages.prediction.monitoring.ShortageSolved;
|
||||
|
||||
import java.time.Clock;
|
||||
|
||||
@SpringBootApplication
|
||||
@EnableScheduling
|
||||
@EntityScan(
|
||||
basePackageClasses = {Configuration.class, Jsr310JpaConverters.class}
|
||||
)
|
||||
public class Configuration {
|
||||
@Bean
|
||||
public Clock clock() {
|
||||
return Clock.systemDefaultZone();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Forecasts forecasts() {
|
||||
return new ForecastsFake();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ShortageEventsFake shortageEvents() {
|
||||
return new ShortageEventsFake();
|
||||
}
|
||||
|
||||
private class ShortageEventsFake implements ShortageEvents {
|
||||
@Override
|
||||
public void emit(NewShortage event) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void emit(ShortageSolved event) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private class ForecastsFake implements Forecasts {
|
||||
@Override
|
||||
public Forecast get(RefNoId refNo, int daysAhead) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,6 @@ import pl.com.bottega.factory.shortages.prediction.Shortages
|
||||
import pl.com.bottega.factory.shortages.prediction.calculation.Forecasts
|
||||
import pl.com.bottega.factory.shortages.prediction.monitoring.persistence.ShortagesDao
|
||||
import pl.com.bottega.factory.shortages.prediction.monitoring.persistence.ShortagesEntity
|
||||
import pl.com.bottega.factory.shortages.prediction.notification.NotificationOfShortage
|
||||
import spock.lang.Specification
|
||||
|
||||
import javax.transaction.Transactional
|
||||
@@ -27,11 +26,11 @@ class ShortagePredictionProcessORMRepositoryTest extends Specification {
|
||||
@Autowired
|
||||
ShortagesDao dao
|
||||
def forecasts = Mock(Forecasts)
|
||||
def notifications = Mock(NotificationOfShortage)
|
||||
def notifications = Mock(ShortageEvents)
|
||||
ShortagePredictionProcessORMRepository repository
|
||||
|
||||
def setup() {
|
||||
dao.deleteAll()
|
||||
dao.deleteAllInBatch()
|
||||
repository = new ShortagePredictionProcessORMRepository(
|
||||
dao, forecasts, notifications
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user