27
common/common-data-access/pom.xml
Normal file
27
common/common-data-access/pom.xml
Normal file
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>common</artifactId>
|
||||
<groupId>com.food.order</groupId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>common-data-access</artifactId>
|
||||
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.postgresql</groupId>
|
||||
<artifactId>postgresql</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.food.order.system.data.access.restaurant.entity;
|
||||
package com.food.order.system.common.data.access.entity;
|
||||
|
||||
|
||||
import lombok.*;
|
||||
@@ -34,6 +34,8 @@ public class RestaurantEntity {
|
||||
|
||||
private BigDecimal productPrice;
|
||||
|
||||
private Boolean productActive;
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.food.order.system.data.access.restaurant.entity;
|
||||
package com.food.order.system.common.data.access.entity;
|
||||
|
||||
import lombok.*;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.food.order.system.data.access.restaurant.exception;
|
||||
package com.food.order.system.common.data.access.exception;
|
||||
|
||||
public class RestaurantDataAccessException extends RuntimeException{
|
||||
public RestaurantDataAccessException(String s) {
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.food.order.system.data.access.restaurant.repository;
|
||||
package com.food.order.system.common.data.access.repository;
|
||||
|
||||
import com.food.order.system.data.access.restaurant.entity.RestaurantEntity;
|
||||
import com.food.order.system.common.data.access.entity.RestaurantEntity;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.food.order.sysyem.valueobject;
|
||||
|
||||
public enum RestaurantOrderStatus {
|
||||
PAID
|
||||
}
|
||||
@@ -14,6 +14,7 @@
|
||||
<modules>
|
||||
<module>common-domain</module>
|
||||
<module>common-application</module>
|
||||
<module>common-data-access</module>
|
||||
</modules>
|
||||
|
||||
<properties>
|
||||
|
||||
Binary file not shown.
@@ -5,8 +5,10 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.autoconfigure.domain.EntityScan;
|
||||
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
|
||||
|
||||
@EnableJpaRepositories("com.food.order.system.data.access")
|
||||
@EntityScan(basePackages = "com.food.order.system.data.access")
|
||||
@EnableJpaRepositories(basePackages = {"com.food.order.system.data.access",
|
||||
"com.food.order.system.common.data.access"})
|
||||
@EntityScan(basePackages = {"com.food.order.system.data.access",
|
||||
"com.food.order.system.common.data.access"})
|
||||
@SpringBootApplication(scanBasePackages = "com.food.order")
|
||||
public class OrderServiceApplication {
|
||||
public static void main(String[] args) {
|
||||
|
||||
Binary file not shown.
@@ -29,6 +29,10 @@
|
||||
<groupId>org.postgresql</groupId>
|
||||
<artifactId>postgresql</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.food.order</groupId>
|
||||
<artifactId>common-data-access</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@@ -1,9 +1,9 @@
|
||||
package com.food.order.system.data.access.restaurant.adapter;
|
||||
|
||||
import com.food.order.sysyem.ports.output.repository.RestaurantRepository;
|
||||
import com.food.order.system.common.data.access.repository.RestaurantJpaRepository;
|
||||
import com.food.order.system.data.access.restaurant.mapper.RestaurantDataAccessMapper;
|
||||
import com.food.order.system.data.access.restaurant.repository.RestaurantJpaRepository;
|
||||
import com.food.order.system.domain.entity.Restaurant;
|
||||
import com.food.order.sysyem.ports.output.repository.RestaurantRepository;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
package com.food.order.system.data.access.restaurant.mapper;
|
||||
|
||||
import com.food.order.system.common.data.access.entity.RestaurantEntity;
|
||||
import com.food.order.system.common.data.access.exception.RestaurantDataAccessException;
|
||||
import com.food.order.system.domain.entity.Product;
|
||||
import com.food.order.system.domain.entity.Restaurant;
|
||||
import com.food.order.sysyem.valueobject.Money;
|
||||
import com.food.order.sysyem.valueobject.ProductId;
|
||||
import com.food.order.sysyem.valueobject.RestaurantId;
|
||||
import com.food.order.system.data.access.restaurant.entity.RestaurantEntity;
|
||||
import com.food.order.system.data.access.restaurant.exception.RestaurantDataAccessException;
|
||||
import com.food.order.system.domain.entity.Product;
|
||||
import com.food.order.system.domain.entity.Restaurant;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
Binary file not shown.
@@ -0,0 +1,8 @@
|
||||
package com.food.order.sysyem.ports.output.message.publisher.restaurantapproval;
|
||||
|
||||
import com.food.order.sysyem.event.publisher.DomainEventPublisher;
|
||||
import com.food.order.system.domain.event.OrderPaidEvent;
|
||||
|
||||
public interface OrderPaidRestaurantRequestMessagePublisher extends DomainEventPublisher<OrderPaidEvent> {
|
||||
|
||||
}
|
||||
Binary file not shown.
@@ -13,10 +13,6 @@
|
||||
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.food.order</groupId>
|
||||
<artifactId>payment-domain</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.food.order</groupId>
|
||||
@@ -32,11 +28,10 @@
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-tx</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.food.order</groupId>
|
||||
<artifactId>payment-domain-core</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
38
pom.xml
38
pom.xml
@@ -16,6 +16,7 @@
|
||||
<module>infrastructure/kafka</module>
|
||||
<module>customer-service</module>
|
||||
<module>payment-service</module>
|
||||
<module>restaurant-service</module>
|
||||
</modules>
|
||||
|
||||
|
||||
@@ -103,6 +104,43 @@
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.food.order</groupId>
|
||||
<artifactId>restaurant-application-service</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.food.order</groupId>
|
||||
<artifactId>common-data-access</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.food.order</groupId>
|
||||
<artifactId>restaurant-dataaccess</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.food.order</groupId>
|
||||
<artifactId>restaurant-messaging</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.food.order</groupId>
|
||||
<artifactId>restaurant-core-domain</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>com.food.order</groupId>
|
||||
<artifactId>restaurant-domain</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>com.food.order</groupId>
|
||||
<artifactId>kafka-consumer</artifactId>
|
||||
|
||||
22
restaurant-service/pom.xml
Normal file
22
restaurant-service/pom.xml
Normal file
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>food-ordering-system</artifactId>
|
||||
<groupId>com.food.order</groupId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>restaurant-service</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
<modules>
|
||||
<module>restaurant-domain</module>
|
||||
<module>restaurant-messaging</module>
|
||||
<module>restaurant-container</module>
|
||||
<module>restaurant-dataaccess</module>
|
||||
</modules>
|
||||
|
||||
|
||||
</project>
|
||||
61
restaurant-service/restaurant-container/pom.xml
Normal file
61
restaurant-service/restaurant-container/pom.xml
Normal file
@@ -0,0 +1,61 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>restaurant-service</artifactId>
|
||||
<groupId>com.food.order</groupId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>restaurant-container</artifactId>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.food.order</groupId>
|
||||
<artifactId>restaurant-core-domain</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.food.order</groupId>
|
||||
<artifactId>restaurant-application-service</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.food.order</groupId>
|
||||
<artifactId>restaurant-dataaccess</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.food.order</groupId>
|
||||
<artifactId>restaurant-messaging</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<image>
|
||||
<name>${project.groupId}/restaurant.service:${project.version}</name>
|
||||
</image>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>install</phase>
|
||||
<goals>
|
||||
<goal>build-image</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.food.order.system.restaurant.container;
|
||||
|
||||
import com.food.order.system.restaurant.domain.core.RestaurantDomainService;
|
||||
import com.food.order.system.restaurant.domain.core.RestaurantDomainServiceImpl;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
public class RestaurantBeanConfig {
|
||||
|
||||
@Bean
|
||||
public RestaurantDomainService restaurantService() {
|
||||
return new RestaurantDomainServiceImpl();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.food.order.system.restaurant.container;
|
||||
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.autoconfigure.domain.EntityScan;
|
||||
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
|
||||
|
||||
@EnableJpaRepositories(basePackages = { "com.food.order.system.data.access.restaurant",
|
||||
"com.food.order.system.common.data.access" })
|
||||
@EntityScan(basePackages = { "com.food.order.system.data.access.restaurant",
|
||||
"com.food.order.system.common.data.access" })
|
||||
@SpringBootApplication(scanBasePackages = "com.food.order")
|
||||
public class RestaurantServiceApplication {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(RestaurantServiceApplication.class, args);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
server:
|
||||
port: 8183
|
||||
|
||||
logging:
|
||||
level:
|
||||
com.food.ordering.system: DEBUG
|
||||
|
||||
restaurant-service:
|
||||
restaurant-approval-request-topic-name: restaurant-approval-request-value
|
||||
restaurant-approval-response-topic-name: restaurant-approval-response-value
|
||||
|
||||
spring:
|
||||
jpa:
|
||||
open-in-view: false
|
||||
show-sql: true
|
||||
database-platform: org.hibernate.dialect.PostgreSQL9Dialect
|
||||
properties:
|
||||
hibernate:
|
||||
dialect: org.hibernate.dialect.PostgreSQL9Dialect
|
||||
datasource:
|
||||
url: jdbc:postgresql://localhost:5432/postgres?currentSchema=restaurant&binaryTransfer=true&reWriteBatchedInserts=true&stringtype=unspecified
|
||||
username: postgres
|
||||
password: postgres
|
||||
driver-class-name: org.postgresql.Driver
|
||||
sql:
|
||||
init:
|
||||
platform: postgres
|
||||
mode: always
|
||||
data-locations: classpath:init-data.sql
|
||||
schema-locations: classpath:init-schema.sql
|
||||
|
||||
kafka-config:
|
||||
bootstrap-servers: localhost:19092, localhost:29092, localhost:39092
|
||||
schema-registry-url-key: schema.registry.url
|
||||
schema-registry-url: http://localhost:8081
|
||||
num-of-partitions: 3
|
||||
replication-factor: 3
|
||||
|
||||
kafka-producer-config:
|
||||
key-serializer-class: org.apache.kafka.common.serialization.StringSerializer
|
||||
value-serializer-class: io.confluent.kafka.serializers.KafkaAvroSerializer
|
||||
compression-type: snappy
|
||||
acks: all
|
||||
batch-size: 16384
|
||||
batch-size-boost-factor: 100
|
||||
linger-ms: 5
|
||||
request-timeout-ms: 60000
|
||||
retry-count: 5
|
||||
|
||||
kafka-consumer-config:
|
||||
key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
|
||||
value-deserializer: io.confluent.kafka.serializers.KafkaAvroDeserializer
|
||||
restaurant-approval-consumer-group-id: restaurant-approval-topic-consumer
|
||||
auto-offset-reset: earliest
|
||||
specific-avro-reader-key: specific.avro.reader
|
||||
specific-avro-reader: true
|
||||
batch-listener: true
|
||||
auto-startup: true
|
||||
concurrency-level: 3
|
||||
session-timeout-ms: 10000
|
||||
heartbeat-interval-ms: 3000
|
||||
max-poll-interval-ms: 300000
|
||||
max-poll-records: 500
|
||||
max-partition-fetch-bytes-default: 1048576
|
||||
max-partition-fetch-bytes-boost-factor: 1
|
||||
poll-timeout-ms: 150
|
||||
@@ -0,0 +1,22 @@
|
||||
INSERT INTO restaurant.restaurants(id, name, active)
|
||||
VALUES ('d215b5f8-0249-4dc5-89a3-51fd148cfb45', 'restaurant_1', TRUE);
|
||||
INSERT INTO restaurant.restaurants(id, name, active)
|
||||
VALUES ('d215b5f8-0249-4dc5-89a3-51fd148cfb46', 'restaurant_2', FALSE);
|
||||
|
||||
INSERT INTO restaurant.products(id, name, price, available)
|
||||
VALUES ('d215b5f8-0249-4dc5-89a3-51fd148cfb47', 'product_1', 25.00, FALSE);
|
||||
INSERT INTO restaurant.products(id, name, price, available)
|
||||
VALUES ('d215b5f8-0249-4dc5-89a3-51fd148cfb48', 'product_2', 50.00, TRUE);
|
||||
INSERT INTO restaurant.products(id, name, price, available)
|
||||
VALUES ('d215b5f8-0249-4dc5-89a3-51fd148cfb49', 'product_3', 20.00, FALSE);
|
||||
INSERT INTO restaurant.products(id, name, price, available)
|
||||
VALUES ('d215b5f8-0249-4dc5-89a3-51fd148cfb50', 'product_4', 40.00, TRUE);
|
||||
|
||||
INSERT INTO restaurant.restaurant_products(id, restaurant_id, product_id)
|
||||
VALUES ('d215b5f8-0249-4dc5-89a3-51fd148cfb51', 'd215b5f8-0249-4dc5-89a3-51fd148cfb45', 'd215b5f8-0249-4dc5-89a3-51fd148cfb47');
|
||||
INSERT INTO restaurant.restaurant_products(id, restaurant_id, product_id)
|
||||
VALUES ('d215b5f8-0249-4dc5-89a3-51fd148cfb52', 'd215b5f8-0249-4dc5-89a3-51fd148cfb45', 'd215b5f8-0249-4dc5-89a3-51fd148cfb48');
|
||||
INSERT INTO restaurant.restaurant_products(id, restaurant_id, product_id)
|
||||
VALUES ('d215b5f8-0249-4dc5-89a3-51fd148cfb53', 'd215b5f8-0249-4dc5-89a3-51fd148cfb46', 'd215b5f8-0249-4dc5-89a3-51fd148cfb49');
|
||||
INSERT INTO restaurant.restaurant_products(id, restaurant_id, product_id)
|
||||
VALUES ('d215b5f8-0249-4dc5-89a3-51fd148cfb54', 'd215b5f8-0249-4dc5-89a3-51fd148cfb46', 'd215b5f8-0249-4dc5-89a3-51fd148cfb50');
|
||||
@@ -0,0 +1,103 @@
|
||||
DROP SCHEMA IF EXISTS restaurant CASCADE;
|
||||
|
||||
CREATE SCHEMA restaurant;
|
||||
|
||||
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
|
||||
|
||||
DROP TABLE IF EXISTS restaurant.restaurants CASCADE;
|
||||
|
||||
CREATE TABLE restaurant.restaurants
|
||||
(
|
||||
id uuid NOT NULL,
|
||||
name character varying COLLATE pg_catalog."default" NOT NULL,
|
||||
active boolean NOT NULL,
|
||||
CONSTRAINT restaurants_pkey PRIMARY KEY (id)
|
||||
);
|
||||
|
||||
DROP TYPE IF EXISTS approval_status;
|
||||
|
||||
CREATE TYPE approval_status AS ENUM ('APPROVED', 'REJECTED');
|
||||
|
||||
DROP TABLE IF EXISTS restaurant.order_approval CASCADE;
|
||||
|
||||
CREATE TABLE restaurant.order_approval
|
||||
(
|
||||
id uuid NOT NULL,
|
||||
restaurant_id uuid NOT NULL,
|
||||
order_id uuid NOT NULL,
|
||||
status approval_status NOT NULL,
|
||||
CONSTRAINT order_approval_pkey PRIMARY KEY (id)
|
||||
);
|
||||
|
||||
DROP TABLE IF EXISTS restaurant.products CASCADE;
|
||||
|
||||
CREATE TABLE restaurant.products
|
||||
(
|
||||
id uuid NOT NULL,
|
||||
name character varying COLLATE pg_catalog."default" NOT NULL,
|
||||
price numeric(10,2) NOT NULL,
|
||||
available boolean NOT NULL,
|
||||
CONSTRAINT products_pkey PRIMARY KEY (id)
|
||||
);
|
||||
|
||||
DROP TABLE IF EXISTS restaurant.restaurant_products CASCADE;
|
||||
|
||||
CREATE TABLE restaurant.restaurant_products
|
||||
(
|
||||
id uuid NOT NULL,
|
||||
restaurant_id uuid NOT NULL,
|
||||
product_id uuid NOT NULL,
|
||||
CONSTRAINT restaurant_products_pkey PRIMARY KEY (id)
|
||||
);
|
||||
|
||||
ALTER TABLE restaurant.restaurant_products
|
||||
ADD CONSTRAINT "FK_RESTAURANT_ID" FOREIGN KEY (restaurant_id)
|
||||
REFERENCES restaurant.restaurants (id) MATCH SIMPLE
|
||||
ON UPDATE NO ACTION
|
||||
ON DELETE RESTRICT
|
||||
NOT VALID;
|
||||
|
||||
ALTER TABLE restaurant.restaurant_products
|
||||
ADD CONSTRAINT "FK_PRODUCT_ID" FOREIGN KEY (product_id)
|
||||
REFERENCES restaurant.products (id) MATCH SIMPLE
|
||||
ON UPDATE NO ACTION
|
||||
ON DELETE RESTRICT
|
||||
NOT VALID;
|
||||
|
||||
DROP MATERIALIZED VIEW IF EXISTS restaurant.order_restaurant_m_view;
|
||||
|
||||
CREATE MATERIALIZED VIEW restaurant.order_restaurant_m_view
|
||||
TABLESPACE pg_default
|
||||
AS
|
||||
SELECT r.id AS restaurant_id,
|
||||
r.name AS restaurant_name,
|
||||
r.active AS restaurant_active,
|
||||
p.id AS product_id,
|
||||
p.name AS product_name,
|
||||
p.price AS product_price,
|
||||
p.available AS product_available
|
||||
FROM restaurant.restaurants r,
|
||||
restaurant.products p,
|
||||
restaurant.restaurant_products rp
|
||||
WHERE r.id = rp.restaurant_id AND p.id = rp.product_id
|
||||
WITH DATA;
|
||||
|
||||
refresh materialized VIEW restaurant.order_restaurant_m_view;
|
||||
|
||||
DROP function IF EXISTS restaurant.refresh_order_restaurant_m_view;
|
||||
|
||||
CREATE OR replace function restaurant.refresh_order_restaurant_m_view()
|
||||
returns trigger
|
||||
AS '
|
||||
BEGIN
|
||||
refresh materialized VIEW restaurant.order_restaurant_m_view;
|
||||
return null;
|
||||
END;
|
||||
' LANGUAGE plpgsql;
|
||||
|
||||
DROP trigger IF EXISTS refresh_order_restaurant_m_view ON restaurant.restaurant_products;
|
||||
|
||||
CREATE trigger refresh_order_restaurant_m_view
|
||||
after INSERT OR UPDATE OR DELETE OR truncate
|
||||
ON restaurant.restaurant_products FOR each statement
|
||||
EXECUTE PROCEDURE restaurant.refresh_order_restaurant_m_view();
|
||||
38
restaurant-service/restaurant-dataaccess/pom.xml
Normal file
38
restaurant-service/restaurant-dataaccess/pom.xml
Normal file
@@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>restaurant-service</artifactId>
|
||||
<groupId>com.food.order</groupId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>restaurant-dataaccess</artifactId>
|
||||
|
||||
|
||||
<dependencies>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.food.order</groupId>
|
||||
<artifactId>restaurant-application-service</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.postgresql</groupId>
|
||||
<artifactId>postgresql</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.food.order</groupId>
|
||||
<artifactId>common-data-access</artifactId>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.food.order.system.data.access.restaurant.adapter;
|
||||
|
||||
import com.food.order.system.data.access.restaurant.mapper.RestaurantDataAccessMapper;
|
||||
import com.food.order.system.data.access.restaurant.repository.OrderApprovalJpaRepository;
|
||||
import com.food.order.system.restaurant.domain.core.entity.OrderApproval;
|
||||
import com.food.ordery.system.restaurant.domain.service.ports.output.repository.OrderApprovalRepository;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class OrderApprovalRepositoryImpl implements OrderApprovalRepository {
|
||||
|
||||
private final OrderApprovalJpaRepository orderApprovalJpaRepository;
|
||||
private final RestaurantDataAccessMapper restaurantDataAccessMapper;
|
||||
|
||||
|
||||
@Override
|
||||
public OrderApproval save(OrderApproval orderApproval) {
|
||||
return restaurantDataAccessMapper
|
||||
.orderApprovalEntityToOrderApproval(orderApprovalJpaRepository
|
||||
.save(restaurantDataAccessMapper.orderApprovalToOrderApprovalEntity(orderApproval)));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.food.order.system.data.access.restaurant.adapter;
|
||||
|
||||
import com.food.order.system.common.data.access.entity.RestaurantEntity;
|
||||
import com.food.order.system.common.data.access.repository.RestaurantJpaRepository;
|
||||
import com.food.order.system.data.access.restaurant.mapper.RestaurantDataAccessMapper;
|
||||
import com.food.order.system.restaurant.domain.core.entity.Restaurant;
|
||||
import com.food.ordery.system.restaurant.domain.service.ports.output.repository.RestaurantRepository;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class RestaurantRepositoryImpl implements RestaurantRepository {
|
||||
|
||||
private final RestaurantJpaRepository restaurantJpaRepository;
|
||||
private final RestaurantDataAccessMapper restaurantDataAccessMapper;
|
||||
|
||||
@Override
|
||||
public Optional<Restaurant> findRestaurantInformation(Restaurant restaurant) {
|
||||
List<UUID> restaurantProducts =
|
||||
restaurantDataAccessMapper.restaurantToRestaurantProducts(restaurant);
|
||||
Optional<List<RestaurantEntity>> restaurantEntities = restaurantJpaRepository
|
||||
.findByRestaurantIdAndProductIdIn(restaurant.getId().getValue(),
|
||||
restaurantProducts);
|
||||
return restaurantEntities.map(restaurantDataAccessMapper::restaurantEntityToRestaurant);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.food.order.system.data.access.restaurant.entity;
|
||||
|
||||
import com.food.order.sysyem.valueobject.OrderApprovalStatus;
|
||||
import lombok.*;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.util.UUID;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Table(name = "order_approval", schema = "restaurant")
|
||||
@Entity
|
||||
public class OrderApprovalEntity {
|
||||
|
||||
@Id
|
||||
private UUID id;
|
||||
private UUID restaurantId;
|
||||
private UUID orderId;
|
||||
@Enumerated(EnumType.STRING)
|
||||
private OrderApprovalStatus status;
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package com.food.order.system.data.access.restaurant.mapper;
|
||||
|
||||
import com.food.order.system.common.data.access.entity.RestaurantEntity;
|
||||
import com.food.order.system.common.data.access.exception.RestaurantDataAccessException;
|
||||
import com.food.order.system.data.access.restaurant.entity.OrderApprovalEntity;
|
||||
import com.food.order.system.restaurant.domain.core.entity.OrderApproval;
|
||||
import com.food.order.system.restaurant.domain.core.entity.OrderDetail;
|
||||
import com.food.order.system.restaurant.domain.core.entity.Product;
|
||||
import com.food.order.system.restaurant.domain.core.entity.Restaurant;
|
||||
import com.food.order.system.restaurant.domain.core.valueobject.OrderApprovalId;
|
||||
import com.food.order.sysyem.valueobject.Money;
|
||||
import com.food.order.sysyem.valueobject.OrderId;
|
||||
import com.food.order.sysyem.valueobject.ProductId;
|
||||
import com.food.order.sysyem.valueobject.RestaurantId;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Component
|
||||
public class RestaurantDataAccessMapper {
|
||||
|
||||
public List<UUID> restaurantToRestaurantProducts(Restaurant restaurant) {
|
||||
return restaurant.getOrderDetail().getProducts().stream()
|
||||
.map(product -> product.getId().getValue())
|
||||
.toList();
|
||||
}
|
||||
|
||||
public Restaurant restaurantEntityToRestaurant(List<RestaurantEntity> restaurantEntities) {
|
||||
RestaurantEntity restaurantEntity =
|
||||
restaurantEntities.stream().findFirst().orElseThrow(() ->
|
||||
new RestaurantDataAccessException("No restaurants found!"));
|
||||
|
||||
List<Product> restaurantProducts = restaurantEntities.stream().map(entity ->
|
||||
Product.builder()
|
||||
.productId(new ProductId(entity.getProductId()))
|
||||
.name(entity.getProductName())
|
||||
.price(new Money(entity.getProductPrice()))
|
||||
.available(entity.getProductActive())
|
||||
.build())
|
||||
.collect(Collectors.toList());
|
||||
|
||||
return Restaurant.builder()
|
||||
.restaurantId(new RestaurantId(restaurantEntity.getRestaurantId()))
|
||||
.orderDetail(OrderDetail.builder()
|
||||
.products(restaurantProducts)
|
||||
.build())
|
||||
.active(restaurantEntity.getRestaurantActive())
|
||||
.build();
|
||||
}
|
||||
|
||||
public OrderApprovalEntity orderApprovalToOrderApprovalEntity(OrderApproval orderApproval) {
|
||||
return OrderApprovalEntity.builder()
|
||||
.id(orderApproval.getId().getValue())
|
||||
.restaurantId(orderApproval.getRestaurantId().getValue())
|
||||
.orderId(orderApproval.getOrderId().getValue())
|
||||
.status(orderApproval.getStatus())
|
||||
.build();
|
||||
}
|
||||
|
||||
public OrderApproval orderApprovalEntityToOrderApproval(OrderApprovalEntity orderApprovalEntity) {
|
||||
return OrderApproval.builder()
|
||||
.orderApprovalId(new OrderApprovalId(orderApprovalEntity.getId()))
|
||||
.restaurantId(new RestaurantId(orderApprovalEntity.getRestaurantId()))
|
||||
.orderId(new OrderId(orderApprovalEntity.getOrderId()))
|
||||
.status(orderApprovalEntity.getStatus())
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.food.order.system.data.access.restaurant.repository;
|
||||
|
||||
import com.food.order.system.data.access.restaurant.entity.OrderApprovalEntity;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
@Repository
|
||||
public interface OrderApprovalJpaRepository extends JpaRepository<OrderApprovalEntity, UUID> {
|
||||
|
||||
|
||||
}
|
||||
22
restaurant-service/restaurant-domain/pom.xml
Normal file
22
restaurant-service/restaurant-domain/pom.xml
Normal file
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>restaurant-service</artifactId>
|
||||
<groupId>com.food.order</groupId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>restaurant-domain</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<modules>
|
||||
<module>restaurant-core-domain</module>
|
||||
<module>restaurant-application-service</module>
|
||||
</modules>
|
||||
|
||||
|
||||
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,39 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>restaurant-domain</artifactId>
|
||||
<groupId>com.food.order</groupId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>restaurant-application-service</artifactId>
|
||||
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.food.order</groupId>
|
||||
<artifactId>restaurant-core-domain</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-validation</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.food.order</groupId>
|
||||
<artifactId>common-domain</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-tx</artifactId>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,63 @@
|
||||
package com.food.ordery.system.restaurant.domain.service;
|
||||
|
||||
import com.food.order.system.restaurant.domain.core.RestaurantDomainService;
|
||||
import com.food.order.system.restaurant.domain.core.entity.Restaurant;
|
||||
import com.food.order.system.restaurant.domain.core.event.OrderApprovalEvent;
|
||||
import com.food.order.system.restaurant.domain.core.exception.RestaurantNotFoundException;
|
||||
import com.food.order.sysyem.valueobject.OrderId;
|
||||
import com.food.ordery.system.restaurant.domain.service.dto.RestaurantApprovalRequest;
|
||||
import com.food.ordery.system.restaurant.domain.service.mapper.RestaurantDataMapper;
|
||||
import com.food.ordery.system.restaurant.domain.service.ports.output.message.publisher.OrderApprovedMessagePublisher;
|
||||
import com.food.ordery.system.restaurant.domain.service.ports.output.message.publisher.OrderRejectedMessagePublisher;
|
||||
import com.food.ordery.system.restaurant.domain.service.ports.output.repository.OrderApprovalRepository;
|
||||
import com.food.ordery.system.restaurant.domain.service.ports.output.repository.RestaurantRepository;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class RestaurantApprovalRequestHelper {
|
||||
|
||||
private final RestaurantDomainService restaurantDomainService;
|
||||
private final RestaurantDataMapper restaurantDataMapper;
|
||||
private final RestaurantRepository restaurantRepository;
|
||||
private final OrderApprovalRepository orderApprovalRepository;
|
||||
private final OrderApprovedMessagePublisher orderApprovedMessagePublisher;
|
||||
private final OrderRejectedMessagePublisher orderRejectedMessagePublisher;
|
||||
|
||||
@Transactional
|
||||
public OrderApprovalEvent persistOrderApproval(RestaurantApprovalRequest request) {
|
||||
log.info("Persisting order approval request: {}", request);
|
||||
List<String> failureMessages = new ArrayList<>();
|
||||
var restaurant = findRestaurant(request);
|
||||
var event = restaurantDomainService.validateOrder
|
||||
(restaurant, failureMessages, orderApprovedMessagePublisher, orderRejectedMessagePublisher);
|
||||
|
||||
orderApprovalRepository.save(restaurant.getOrderApproval());
|
||||
return event;
|
||||
|
||||
}
|
||||
|
||||
private Restaurant findRestaurant(RestaurantApprovalRequest request) {
|
||||
var restaurant = restaurantDataMapper.restaurantApprovalRequestToRestaurant(request);
|
||||
var resultRestaurant = restaurantRepository.findRestaurantInformation(restaurant).orElseThrow(
|
||||
() -> new RestaurantNotFoundException("Restaurant not found")
|
||||
);
|
||||
restaurant.setActive(resultRestaurant.isActive());
|
||||
restaurant.getOrderDetail().getProducts().forEach(product -> {
|
||||
resultRestaurant.getOrderDetail().getProducts().forEach(p -> {
|
||||
if (p.getId().equals(product.getId())) {
|
||||
p.updateWithConfirmedNamePriceAndAvailablity(p.getName(),p.getPrice(), p.isAvailable());
|
||||
}});
|
||||
});
|
||||
restaurant.getOrderDetail().setId(new OrderId(UUID.fromString(request.getOrderId())));
|
||||
return restaurant;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.food.ordery.system.restaurant.domain.service;
|
||||
|
||||
import com.food.ordery.system.restaurant.domain.service.dto.RestaurantApprovalRequest;
|
||||
import com.food.ordery.system.restaurant.domain.service.ports.input.message.listener.RestaurantApprovalRequestMessageListener;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class RestaurantApprovalRequestMessageListenerImpl implements RestaurantApprovalRequestMessageListener {
|
||||
|
||||
private final RestaurantApprovalRequestHelper restaurantApprovalRequestHelper;
|
||||
|
||||
@Override
|
||||
public void approveOrder(RestaurantApprovalRequest request) {
|
||||
var event = restaurantApprovalRequestHelper.persistOrderApproval(request);
|
||||
event.fire();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.food.ordery.system.restaurant.domain.service.config;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Data
|
||||
@Configuration
|
||||
@ConfigurationProperties(prefix = "restaurant-service")
|
||||
public class RestaurantServiceConfig {
|
||||
|
||||
private String restaurantApprovalRequestTopicName;
|
||||
private String restaurantApprovalResponseTopicName;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.food.ordery.system.restaurant.domain.service.dto;
|
||||
|
||||
import com.food.order.system.restaurant.domain.core.entity.Product;
|
||||
import com.food.order.sysyem.valueobject.RestaurantOrderStatus;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
|
||||
@Getter
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
public class RestaurantApprovalRequest {
|
||||
private String id;
|
||||
private String sagaId;
|
||||
private String restaurantId;
|
||||
private String orderId;
|
||||
private RestaurantOrderStatus status;
|
||||
private List<Product> products;
|
||||
private BigDecimal price;
|
||||
private Instant createdAt;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.food.ordery.system.restaurant.domain.service.exception;
|
||||
|
||||
import com.food.order.sysyem.exception.DomainException;
|
||||
|
||||
public class RestaurantApplicationServiceException extends DomainException {
|
||||
|
||||
public RestaurantApplicationServiceException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public RestaurantApplicationServiceException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.food.ordery.system.restaurant.domain.service.mapper;
|
||||
|
||||
import com.food.order.system.restaurant.domain.core.entity.OrderDetail;
|
||||
import com.food.order.system.restaurant.domain.core.entity.Product;
|
||||
import com.food.order.system.restaurant.domain.core.entity.Restaurant;
|
||||
import com.food.order.sysyem.valueobject.Money;
|
||||
import com.food.order.sysyem.valueobject.OrderId;
|
||||
import com.food.order.sysyem.valueobject.OrderStatus;
|
||||
import com.food.order.sysyem.valueobject.RestaurantId;
|
||||
import com.food.ordery.system.restaurant.domain.service.dto.RestaurantApprovalRequest;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
@Component
|
||||
public class RestaurantDataMapper {
|
||||
|
||||
public Restaurant restaurantApprovalRequestToRestaurant(RestaurantApprovalRequest request) {
|
||||
return Restaurant.builder()
|
||||
.restaurantId(new RestaurantId(UUID.fromString(request.getRestaurantId())))
|
||||
.orderDetail(OrderDetail.builder()
|
||||
.orderId(new OrderId(UUID.fromString(request.getOrderId())))
|
||||
.products(request.getProducts().stream().map(
|
||||
product -> Product.builder()
|
||||
.productId(product.getId())
|
||||
.quantity(product.getQuantity())
|
||||
|
||||
.build()
|
||||
).toList())
|
||||
.totalAmount(new Money(request.getPrice()))
|
||||
.status(OrderStatus.valueOf(request.getStatus().name()))
|
||||
.build())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.food.ordery.system.restaurant.domain.service.ports.input.message.listener;
|
||||
|
||||
import com.food.ordery.system.restaurant.domain.service.dto.RestaurantApprovalRequest;
|
||||
|
||||
public interface RestaurantApprovalRequestMessageListener {
|
||||
void approveOrder(RestaurantApprovalRequest request);
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.food.ordery.system.restaurant.domain.service.ports.output.message.publisher;
|
||||
|
||||
import com.food.order.system.restaurant.domain.core.event.OrderApprovedEvent;
|
||||
import com.food.order.sysyem.event.publisher.DomainEventPublisher;
|
||||
|
||||
public interface OrderApprovedMessagePublisher extends DomainEventPublisher<OrderApprovedEvent> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.food.ordery.system.restaurant.domain.service.ports.output.message.publisher;
|
||||
|
||||
import com.food.order.system.restaurant.domain.core.event.OrderRejectedEvent;
|
||||
import com.food.order.sysyem.event.publisher.DomainEventPublisher;
|
||||
|
||||
public interface OrderRejectedMessagePublisher extends DomainEventPublisher<OrderRejectedEvent> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.food.ordery.system.restaurant.domain.service.ports.output.repository;
|
||||
|
||||
import com.food.order.system.restaurant.domain.core.entity.OrderApproval;
|
||||
|
||||
public interface OrderApprovalRepository {
|
||||
OrderApproval save(OrderApproval orderApproval);
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.food.ordery.system.restaurant.domain.service.ports.output.repository;
|
||||
|
||||
import com.food.order.system.restaurant.domain.core.entity.Restaurant;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public interface RestaurantRepository {
|
||||
Optional<Restaurant> findRestaurantInformation(Restaurant restaurant);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>restaurant-domain</artifactId>
|
||||
<groupId>com.food.order</groupId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>restaurant-core-domain</artifactId>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.food.order</groupId>
|
||||
<artifactId>common-domain</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.food.order.system.restaurant.domain.core;
|
||||
|
||||
import com.food.order.system.restaurant.domain.core.entity.Restaurant;
|
||||
import com.food.order.system.restaurant.domain.core.event.OrderApprovalEvent;
|
||||
import com.food.order.system.restaurant.domain.core.event.OrderApprovedEvent;
|
||||
import com.food.order.system.restaurant.domain.core.event.OrderRejectedEvent;
|
||||
import com.food.order.sysyem.event.publisher.DomainEventPublisher;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface RestaurantDomainService {
|
||||
OrderApprovalEvent validateOrder(Restaurant restaurant,
|
||||
List<String> failureMessages,
|
||||
DomainEventPublisher<OrderApprovedEvent> publisher,
|
||||
DomainEventPublisher<OrderRejectedEvent> rejectedPublisher);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package com.food.order.system.restaurant.domain.core;
|
||||
|
||||
import com.food.order.system.restaurant.domain.core.entity.Restaurant;
|
||||
import com.food.order.system.restaurant.domain.core.event.OrderApprovalEvent;
|
||||
import com.food.order.system.restaurant.domain.core.event.OrderApprovedEvent;
|
||||
import com.food.order.system.restaurant.domain.core.event.OrderRejectedEvent;
|
||||
import com.food.order.sysyem.event.publisher.DomainEventPublisher;
|
||||
import com.food.order.sysyem.valueobject.OrderApprovalStatus;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.List;
|
||||
|
||||
import static com.food.order.sysyem.DomainConstants.UTC;
|
||||
|
||||
@Slf4j
|
||||
public class RestaurantDomainServiceImpl implements RestaurantDomainService {
|
||||
|
||||
@Override
|
||||
public OrderApprovalEvent validateOrder(Restaurant restaurant,
|
||||
List<String> failureMessages,
|
||||
DomainEventPublisher<OrderApprovedEvent> publisher,
|
||||
DomainEventPublisher<OrderRejectedEvent> rejectedPublisher) {
|
||||
restaurant.validateOrder(failureMessages);
|
||||
log.info("Order validation with id {}", restaurant.getOrderDetail().getId());
|
||||
if (failureMessages.isEmpty()) {
|
||||
log.info("Order validation with id {} is successful", restaurant.getOrderDetail().getId());
|
||||
restaurant.constructOrderApproval(OrderApprovalStatus.APPROVED);
|
||||
return new OrderApprovedEvent(restaurant.getOrderApproval(), restaurant.getId(),
|
||||
failureMessages, ZonedDateTime.now(ZoneId.of(UTC)), publisher);
|
||||
} else {
|
||||
log.info("Order validation with id {} is failed", restaurant.getOrderDetail().getId());
|
||||
restaurant.constructOrderApproval(OrderApprovalStatus.REJECTED);
|
||||
return new OrderRejectedEvent(restaurant.getOrderApproval(), restaurant.getId(),
|
||||
failureMessages, ZonedDateTime.now(), rejectedPublisher);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package com.food.order.system.restaurant.domain.core.entity;
|
||||
|
||||
import com.food.order.system.restaurant.domain.core.valueobject.OrderApprovalId;
|
||||
import com.food.order.sysyem.entity.BaseEntity;
|
||||
import com.food.order.sysyem.valueobject.OrderApprovalStatus;
|
||||
import com.food.order.sysyem.valueobject.OrderId;
|
||||
import com.food.order.sysyem.valueobject.RestaurantId;
|
||||
|
||||
public class OrderApproval extends BaseEntity<OrderApprovalId> {
|
||||
|
||||
private final RestaurantId restaurantId;
|
||||
private final OrderId orderId;
|
||||
private final OrderApprovalStatus status;
|
||||
|
||||
private OrderApproval(Builder builder) {
|
||||
setId(builder.orderApprovalId);
|
||||
restaurantId = builder.restaurantId;
|
||||
orderId = builder.orderId;
|
||||
status = builder.status;
|
||||
}
|
||||
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
public RestaurantId getRestaurantId() {
|
||||
return restaurantId;
|
||||
}
|
||||
|
||||
public OrderId getOrderId() {
|
||||
return orderId;
|
||||
}
|
||||
|
||||
public OrderApprovalStatus getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
public static final class Builder {
|
||||
private OrderApprovalId orderApprovalId;
|
||||
private RestaurantId restaurantId;
|
||||
private OrderId orderId;
|
||||
private OrderApprovalStatus status;
|
||||
|
||||
private Builder() {
|
||||
}
|
||||
|
||||
public Builder orderApprovalId(OrderApprovalId val) {
|
||||
orderApprovalId = val;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder restaurantId(RestaurantId val) {
|
||||
restaurantId = val;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder orderId(OrderId val) {
|
||||
orderId = val;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder status(OrderApprovalStatus val) {
|
||||
status = val;
|
||||
return this;
|
||||
}
|
||||
|
||||
public OrderApproval build() {
|
||||
return new OrderApproval(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package com.food.order.system.restaurant.domain.core.entity;
|
||||
|
||||
import com.food.order.sysyem.entity.BaseEntity;
|
||||
import com.food.order.sysyem.valueobject.Money;
|
||||
import com.food.order.sysyem.valueobject.OrderId;
|
||||
import com.food.order.sysyem.valueobject.OrderStatus;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class OrderDetail extends BaseEntity<OrderId> {
|
||||
private OrderStatus status;
|
||||
private Money totalAmount;
|
||||
private final List<Product> products;
|
||||
|
||||
private OrderDetail(Builder builder) {
|
||||
setId(builder.orderId);
|
||||
status = builder.status;
|
||||
totalAmount = builder.totalAmount;
|
||||
products = builder.products;
|
||||
}
|
||||
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
public OrderStatus getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public Money getTotalAmount() {
|
||||
return totalAmount;
|
||||
}
|
||||
|
||||
public List<Product> getProducts() {
|
||||
return products;
|
||||
}
|
||||
|
||||
|
||||
public static final class Builder {
|
||||
private OrderId orderId;
|
||||
private OrderStatus status;
|
||||
private Money totalAmount;
|
||||
private List<Product> products;
|
||||
|
||||
private Builder() {
|
||||
}
|
||||
|
||||
public Builder orderId(OrderId val) {
|
||||
orderId = val;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder status(OrderStatus val) {
|
||||
status = val;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder totalAmount(Money val) {
|
||||
totalAmount = val;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder products(List<Product> val) {
|
||||
products = val;
|
||||
return this;
|
||||
}
|
||||
|
||||
public OrderDetail build() {
|
||||
return new OrderDetail(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
package com.food.order.system.restaurant.domain.core.entity;
|
||||
|
||||
import com.food.order.sysyem.entity.BaseEntity;
|
||||
import com.food.order.sysyem.valueobject.Money;
|
||||
import com.food.order.sysyem.valueobject.ProductId;
|
||||
|
||||
public class Product extends BaseEntity<ProductId> {
|
||||
|
||||
private String name;
|
||||
private Money price;
|
||||
private final int quantity;
|
||||
private boolean available;
|
||||
|
||||
public void updateWithConfirmedNamePriceAndAvailablity(String name, Money price, boolean available) {
|
||||
this.name = name;
|
||||
this.price = price;
|
||||
this.available = available;
|
||||
}
|
||||
|
||||
private Product(Builder builder) {
|
||||
setId(builder.productId);
|
||||
name = builder.name;
|
||||
price = builder.price;
|
||||
quantity = builder.quantity;
|
||||
available = builder.available;
|
||||
}
|
||||
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public Money getPrice() {
|
||||
return price;
|
||||
}
|
||||
|
||||
public int getQuantity() {
|
||||
return quantity;
|
||||
}
|
||||
|
||||
public boolean isAvailable() {
|
||||
return available;
|
||||
}
|
||||
|
||||
|
||||
public static final class Builder {
|
||||
private ProductId productId;
|
||||
private String name;
|
||||
private Money price;
|
||||
private int quantity;
|
||||
private boolean available;
|
||||
|
||||
private Builder() {
|
||||
}
|
||||
|
||||
public Builder productId(ProductId val) {
|
||||
productId = val;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder name(String val) {
|
||||
name = val;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder price(Money val) {
|
||||
price = val;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder quantity(int val) {
|
||||
quantity = val;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder available(boolean val) {
|
||||
available = val;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Product build() {
|
||||
return new Product(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
package com.food.order.system.restaurant.domain.core.entity;
|
||||
|
||||
import com.food.order.system.restaurant.domain.core.valueobject.OrderApprovalId;
|
||||
import com.food.order.sysyem.entity.AggregateRoot;
|
||||
import com.food.order.sysyem.valueobject.Money;
|
||||
import com.food.order.sysyem.valueobject.OrderApprovalStatus;
|
||||
import com.food.order.sysyem.valueobject.OrderStatus;
|
||||
import com.food.order.sysyem.valueobject.RestaurantId;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public class Restaurant extends AggregateRoot<RestaurantId> {
|
||||
private OrderApproval orderApproval;
|
||||
private boolean active;
|
||||
private final OrderDetail orderDetail;
|
||||
|
||||
public void validateOrder(List<String> failureMessages){
|
||||
if (!orderDetail.getStatus().equals(OrderStatus.PAID)){
|
||||
failureMessages.add("Order is not paid");
|
||||
}
|
||||
var totalAmount = orderDetail.getProducts()
|
||||
.stream()
|
||||
.map(product -> {
|
||||
if (Boolean.FALSE.equals(product.isAvailable()))
|
||||
{
|
||||
failureMessages.add("Product is not available");
|
||||
}
|
||||
return product.getPrice().multiply(product.getQuantity());
|
||||
})
|
||||
.reduce(Money.ZERO, Money::add);
|
||||
|
||||
if(!totalAmount.equals(orderDetail.getTotalAmount()))
|
||||
{
|
||||
failureMessages.add("Total amount is not correct");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void constructOrderApproval(OrderApprovalStatus status){
|
||||
this.orderApproval = OrderApproval.builder()
|
||||
.orderApprovalId(new OrderApprovalId(UUID.randomUUID()))
|
||||
.restaurantId(this.getId())
|
||||
.orderId(this.getOrderDetail().getId())
|
||||
.status(status)
|
||||
.build();
|
||||
}
|
||||
|
||||
public void setActive(boolean active) {
|
||||
this.active = active;
|
||||
}
|
||||
|
||||
private Restaurant(Builder builder) {
|
||||
setId(builder.restaurantId);
|
||||
orderApproval = builder.orderApproval;
|
||||
active = builder.active;
|
||||
orderDetail = builder.orderDetail;
|
||||
}
|
||||
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
public OrderApproval getOrderApproval() {
|
||||
return orderApproval;
|
||||
}
|
||||
|
||||
public boolean isActive() {
|
||||
return active;
|
||||
}
|
||||
|
||||
public OrderDetail getOrderDetail() {
|
||||
return orderDetail;
|
||||
}
|
||||
|
||||
|
||||
public static final class Builder {
|
||||
private RestaurantId restaurantId;
|
||||
private OrderApproval orderApproval;
|
||||
private boolean active;
|
||||
private OrderDetail orderDetail;
|
||||
|
||||
private Builder() {
|
||||
}
|
||||
|
||||
public Builder restaurantId(RestaurantId val) {
|
||||
restaurantId = val;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder orderApproval(OrderApproval val) {
|
||||
orderApproval = val;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder active(boolean val) {
|
||||
active = val;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder orderDetail(OrderDetail val) {
|
||||
orderDetail = val;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Restaurant build() {
|
||||
return new Restaurant(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.food.order.system.restaurant.domain.core.event;
|
||||
|
||||
import com.food.order.system.restaurant.domain.core.entity.OrderApproval;
|
||||
import com.food.order.sysyem.event.DomainEvent;
|
||||
import com.food.order.sysyem.valueobject.RestaurantId;
|
||||
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.List;
|
||||
|
||||
public abstract class OrderApprovalEvent implements DomainEvent<OrderApproval> {
|
||||
|
||||
private final OrderApproval orderApproval;
|
||||
private final RestaurantId restaurantId;
|
||||
private final List<String > failureMessages;
|
||||
private final ZonedDateTime createdAt;
|
||||
|
||||
public OrderApprovalEvent(OrderApproval orderApproval,
|
||||
RestaurantId restaurantId,
|
||||
List<String> failureMessages,
|
||||
ZonedDateTime createdAt) {
|
||||
this.orderApproval = orderApproval;
|
||||
this.restaurantId = restaurantId;
|
||||
this.failureMessages = failureMessages;
|
||||
this.createdAt = createdAt;
|
||||
}
|
||||
|
||||
public OrderApproval getOrderApproval() {
|
||||
return orderApproval;
|
||||
}
|
||||
|
||||
public RestaurantId getRestaurantId() {
|
||||
return restaurantId;
|
||||
}
|
||||
|
||||
public List<String> getFailureMessages() {
|
||||
return failureMessages;
|
||||
}
|
||||
|
||||
public ZonedDateTime getCreatedAt() {
|
||||
return createdAt;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.food.order.system.restaurant.domain.core.event;
|
||||
|
||||
import com.food.order.system.restaurant.domain.core.entity.OrderApproval;
|
||||
import com.food.order.sysyem.event.publisher.DomainEventPublisher;
|
||||
import com.food.order.sysyem.valueobject.RestaurantId;
|
||||
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.List;
|
||||
|
||||
public class OrderApprovedEvent extends OrderApprovalEvent {
|
||||
|
||||
|
||||
private final DomainEventPublisher<OrderApprovedEvent> publisher;
|
||||
|
||||
public OrderApprovedEvent(OrderApproval orderApproval,
|
||||
RestaurantId restaurantId,
|
||||
List<String> failureMessages,
|
||||
ZonedDateTime createdAt,
|
||||
DomainEventPublisher<OrderApprovedEvent> publisher) {
|
||||
super(orderApproval, restaurantId, failureMessages, createdAt);
|
||||
this.publisher = publisher;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fire() {
|
||||
publisher.publish(this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.food.order.system.restaurant.domain.core.event;
|
||||
|
||||
import com.food.order.system.restaurant.domain.core.entity.OrderApproval;
|
||||
import com.food.order.sysyem.event.publisher.DomainEventPublisher;
|
||||
import com.food.order.sysyem.valueobject.RestaurantId;
|
||||
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.List;
|
||||
|
||||
public class OrderRejectedEvent extends OrderApprovalEvent {
|
||||
|
||||
private final DomainEventPublisher<OrderRejectedEvent> publisher;
|
||||
|
||||
public OrderRejectedEvent(OrderApproval orderApproval,
|
||||
RestaurantId restaurantId,
|
||||
List<String> failureMessages,
|
||||
ZonedDateTime createdAt,
|
||||
DomainEventPublisher<OrderRejectedEvent> publisher) {
|
||||
super(orderApproval, restaurantId, failureMessages, createdAt);
|
||||
this.publisher = publisher;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fire() {
|
||||
publisher.publish(this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.food.order.system.restaurant.domain.core.exception;
|
||||
|
||||
import com.food.order.sysyem.exception.DomainException;
|
||||
|
||||
public class RestaurantDomainException extends DomainException {
|
||||
public RestaurantDomainException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public RestaurantDomainException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.food.order.system.restaurant.domain.core.exception;
|
||||
|
||||
import com.food.order.sysyem.exception.DomainException;
|
||||
|
||||
public class RestaurantNotFoundException extends DomainException {
|
||||
public RestaurantNotFoundException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public RestaurantNotFoundException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.food.order.system.restaurant.domain.core.valueobject;
|
||||
|
||||
import com.food.order.sysyem.valueobject.BaseId;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class OrderApprovalId extends BaseId<UUID> {
|
||||
public OrderApprovalId(UUID value) {
|
||||
super(value);
|
||||
}
|
||||
}
|
||||
35
restaurant-service/restaurant-messaging/pom.xml
Normal file
35
restaurant-service/restaurant-messaging/pom.xml
Normal file
@@ -0,0 +1,35 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>restaurant-service</artifactId>
|
||||
<groupId>com.food.order</groupId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>restaurant-messaging</artifactId>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.food.order</groupId>
|
||||
<artifactId>restaurant-application-service</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.food.order</groupId>
|
||||
<artifactId>kafka-producer</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.food.order</groupId>
|
||||
<artifactId>kafka-consumer</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.food.order</groupId>
|
||||
<artifactId>kafka-model</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,48 @@
|
||||
package com.food.order.system.restaurant.messaging.listener.kafka;
|
||||
|
||||
|
||||
import com.food.order.system.kafka.consumer.KafkaConsumer;
|
||||
import com.food.order.system.kafka.order.avro.model.RestaurantApprovalRequestAvroModel;
|
||||
import com.food.order.system.restaurant.messaging.mapper.RestaurantMessagingDataMapper;
|
||||
import com.food.ordery.system.restaurant.domain.service.ports.input.message.listener.RestaurantApprovalRequestMessageListener;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.kafka.annotation.KafkaListener;
|
||||
import org.springframework.kafka.support.KafkaHeaders;
|
||||
import org.springframework.messaging.handler.annotation.Header;
|
||||
import org.springframework.messaging.handler.annotation.Payload;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class RestaurantApprovalRequestKafkaListener implements KafkaConsumer<RestaurantApprovalRequestAvroModel> {
|
||||
|
||||
private final RestaurantApprovalRequestMessageListener restaurantApprovalRequestMessageListener;
|
||||
private final RestaurantMessagingDataMapper restaurantMessagingDataMapper;
|
||||
|
||||
|
||||
@Override
|
||||
@KafkaListener(id = "${kafka-consumer-config.restaurant-approval-consumer-group-id}",
|
||||
topics = "${restaurant-service.restaurant-approval-request-topic-name}")
|
||||
public void receive(@Payload List<RestaurantApprovalRequestAvroModel> messages,
|
||||
@Header(KafkaHeaders.RECEIVED_MESSAGE_KEY) List<String> keys,
|
||||
@Header(KafkaHeaders.RECEIVED_PARTITION_ID) List<Integer> partitions,
|
||||
@Header(KafkaHeaders.OFFSET) List<Long> offsets) {
|
||||
log.info("{} number of orders approval requests received with keys {}, partitions {} and offsets {}" +
|
||||
", sending for restaurant approval",
|
||||
messages.size(),
|
||||
keys.toString(),
|
||||
partitions.toString(),
|
||||
offsets.toString());
|
||||
|
||||
messages.forEach(restaurantApprovalRequestAvroModel -> {
|
||||
log.info("Processing order approval for order id: {}", restaurantApprovalRequestAvroModel.getOrderId());
|
||||
restaurantApprovalRequestMessageListener.approveOrder(restaurantMessagingDataMapper.
|
||||
restaurantApprovalRequestAvroModelToRestaurantApproval(restaurantApprovalRequestAvroModel));
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package com.food.order.system.restaurant.messaging.mapper;
|
||||
|
||||
|
||||
import com.food.order.system.kafka.order.avro.model.OrderApprovalStatus;
|
||||
import com.food.order.system.kafka.order.avro.model.RestaurantApprovalRequestAvroModel;
|
||||
import com.food.order.system.kafka.order.avro.model.RestaurantApprovalResponseAvroModel;
|
||||
import com.food.order.system.restaurant.domain.core.entity.Product;
|
||||
import com.food.order.system.restaurant.domain.core.event.OrderApprovedEvent;
|
||||
import com.food.order.system.restaurant.domain.core.event.OrderRejectedEvent;
|
||||
import com.food.order.sysyem.valueobject.ProductId;
|
||||
import com.food.order.sysyem.valueobject.RestaurantOrderStatus;
|
||||
import com.food.ordery.system.restaurant.domain.service.dto.RestaurantApprovalRequest;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Component
|
||||
public class RestaurantMessagingDataMapper {
|
||||
public RestaurantApprovalResponseAvroModel
|
||||
orderApprovedEventToRestaurantApprovalResponseAvroModel(OrderApprovedEvent orderApprovedEvent) {
|
||||
return RestaurantApprovalResponseAvroModel.newBuilder()
|
||||
.setId(UUID.randomUUID().toString())
|
||||
.setSagaId("")
|
||||
.setOrderId(orderApprovedEvent.getOrderApproval().getOrderId().getValue().toString())
|
||||
.setRestaurantId(orderApprovedEvent.getRestaurantId().getValue().toString())
|
||||
.setCreatedAt(orderApprovedEvent.getCreatedAt().toInstant())
|
||||
.setOrderApprovalStatus(OrderApprovalStatus.valueOf(orderApprovedEvent.
|
||||
getOrderApproval().getStatus().name()))
|
||||
.setFailureMessages(orderApprovedEvent.getFailureMessages())
|
||||
.build();
|
||||
}
|
||||
|
||||
public RestaurantApprovalResponseAvroModel
|
||||
orderRejectedEventToRestaurantApprovalResponseAvroModel(OrderRejectedEvent orderRejectedEvent) {
|
||||
return RestaurantApprovalResponseAvroModel.newBuilder()
|
||||
.setId(UUID.randomUUID().toString())
|
||||
.setSagaId("")
|
||||
.setOrderId(orderRejectedEvent.getOrderApproval().getOrderId().getValue().toString())
|
||||
.setRestaurantId(orderRejectedEvent.getRestaurantId().getValue().toString())
|
||||
.setCreatedAt(orderRejectedEvent.getCreatedAt().toInstant())
|
||||
.setOrderApprovalStatus(OrderApprovalStatus.valueOf(orderRejectedEvent.
|
||||
getOrderApproval().getStatus().name()))
|
||||
.setFailureMessages(orderRejectedEvent.getFailureMessages())
|
||||
.build();
|
||||
}
|
||||
|
||||
public RestaurantApprovalRequest
|
||||
restaurantApprovalRequestAvroModelToRestaurantApproval(RestaurantApprovalRequestAvroModel
|
||||
restaurantApprovalRequestAvroModel) {
|
||||
return RestaurantApprovalRequest.builder()
|
||||
.id(restaurantApprovalRequestAvroModel.getId())
|
||||
.sagaId(restaurantApprovalRequestAvroModel.getSagaId())
|
||||
.restaurantId(restaurantApprovalRequestAvroModel.getRestaurantId())
|
||||
.orderId(restaurantApprovalRequestAvroModel.getOrderId())
|
||||
.status(RestaurantOrderStatus.valueOf(restaurantApprovalRequestAvroModel
|
||||
.getRestaurantOrderStatus().name()))
|
||||
.products(restaurantApprovalRequestAvroModel.getProducts()
|
||||
.stream().map(avroModel ->
|
||||
Product.builder()
|
||||
.productId(new ProductId(UUID.fromString(avroModel.getId())))
|
||||
.quantity(avroModel.getQuantity())
|
||||
.build())
|
||||
.collect(Collectors.toList()))
|
||||
.price(restaurantApprovalRequestAvroModel.getPrice())
|
||||
.createdAt(restaurantApprovalRequestAvroModel.getCreatedAt())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package com.food.order.system.restaurant.messaging.publisher.kafka;
|
||||
|
||||
|
||||
import com.food.order.system.kafka.order.avro.model.RestaurantApprovalResponseAvroModel;
|
||||
import com.food.order.system.kafka.producer.KafkaMessageHelper;
|
||||
import com.food.order.system.kafka.producer.service.KafkaProducer;
|
||||
import com.food.order.system.restaurant.domain.core.event.OrderApprovedEvent;
|
||||
import com.food.order.system.restaurant.messaging.mapper.RestaurantMessagingDataMapper;
|
||||
import com.food.ordery.system.restaurant.domain.service.config.RestaurantServiceConfig;
|
||||
import com.food.ordery.system.restaurant.domain.service.ports.output.message.publisher.OrderApprovedMessagePublisher;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class OrderApprovedKafkaMessagePublisher implements OrderApprovedMessagePublisher {
|
||||
|
||||
private final RestaurantMessagingDataMapper restaurantMessagingDataMapper;
|
||||
private final KafkaProducer<String, RestaurantApprovalResponseAvroModel> kafkaProducer;
|
||||
private final RestaurantServiceConfig restaurantServiceConfigData;
|
||||
private final KafkaMessageHelper kafkaMessageHelper;
|
||||
|
||||
|
||||
@Override
|
||||
public void publish(OrderApprovedEvent orderApprovedEvent) {
|
||||
String orderId = orderApprovedEvent.getOrderApproval().getOrderId().getValue().toString();
|
||||
|
||||
log.info("Received OrderApprovedEvent for order id: {}", orderId);
|
||||
|
||||
try {
|
||||
RestaurantApprovalResponseAvroModel restaurantApprovalResponseAvroModel =
|
||||
restaurantMessagingDataMapper
|
||||
.orderApprovedEventToRestaurantApprovalResponseAvroModel(orderApprovedEvent);
|
||||
|
||||
kafkaProducer.send(restaurantServiceConfigData.getRestaurantApprovalResponseTopicName(),
|
||||
orderId,
|
||||
restaurantApprovalResponseAvroModel,
|
||||
kafkaMessageHelper.getKafkaCallBack(restaurantServiceConfigData
|
||||
.getRestaurantApprovalResponseTopicName(),
|
||||
restaurantApprovalResponseAvroModel,
|
||||
orderId,
|
||||
"RestaurantApprovalResponseAvroModel"));
|
||||
|
||||
log.info("RestaurantApprovalResponseAvroModel sent to kafka at: {}", System.nanoTime());
|
||||
} catch (Exception e) {
|
||||
log.error("Error while sending RestaurantApprovalResponseAvroModel message" +
|
||||
" to kafka with order id: {}, error: {}", orderId, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package com.food.order.system.restaurant.messaging.publisher.kafka;
|
||||
|
||||
|
||||
import com.food.order.system.kafka.order.avro.model.RestaurantApprovalResponseAvroModel;
|
||||
import com.food.order.system.kafka.producer.KafkaMessageHelper;
|
||||
import com.food.order.system.kafka.producer.service.KafkaProducer;
|
||||
import com.food.order.system.restaurant.domain.core.event.OrderRejectedEvent;
|
||||
import com.food.order.system.restaurant.messaging.mapper.RestaurantMessagingDataMapper;
|
||||
import com.food.ordery.system.restaurant.domain.service.config.RestaurantServiceConfig;
|
||||
import com.food.ordery.system.restaurant.domain.service.ports.output.message.publisher.OrderRejectedMessagePublisher;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
@Component
|
||||
public class OrderRejectedKafkaMessagePublisher implements OrderRejectedMessagePublisher {
|
||||
|
||||
private final RestaurantMessagingDataMapper restaurantMessagingDataMapper;
|
||||
private final KafkaProducer<String, RestaurantApprovalResponseAvroModel> kafkaProducer;
|
||||
private final RestaurantServiceConfig restaurantServiceConfigData;
|
||||
private final KafkaMessageHelper kafkaMessageHelper;
|
||||
|
||||
|
||||
@Override
|
||||
public void publish(OrderRejectedEvent orderRejectedEvent) {
|
||||
String orderId = orderRejectedEvent.getOrderApproval().getOrderId().getValue().toString();
|
||||
|
||||
log.info("Received OrderRejectedEvent for order id: {}", orderId);
|
||||
|
||||
try {
|
||||
RestaurantApprovalResponseAvroModel restaurantApprovalResponseAvroModel =
|
||||
restaurantMessagingDataMapper
|
||||
.orderRejectedEventToRestaurantApprovalResponseAvroModel(orderRejectedEvent);
|
||||
|
||||
kafkaProducer.send(restaurantServiceConfigData.getRestaurantApprovalResponseTopicName(),
|
||||
orderId,
|
||||
restaurantApprovalResponseAvroModel,
|
||||
kafkaMessageHelper.getKafkaCallBack(restaurantServiceConfigData
|
||||
.getRestaurantApprovalResponseTopicName(),
|
||||
restaurantApprovalResponseAvroModel,
|
||||
orderId,
|
||||
"RestaurantApprovalResponseAvroModel"));
|
||||
|
||||
log.info("RestaurantApprovalResponseAvroModel sent to kafka at: {}", System.nanoTime());
|
||||
} catch (Exception e) {
|
||||
log.error("Error while sending RestaurantApprovalResponseAvroModel message" +
|
||||
" to kafka with order id: {}, error: {}", orderId, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user