diff --git a/common/common-data-access/pom.xml b/common/common-data-access/pom.xml
new file mode 100644
index 0000000..b5079c4
--- /dev/null
+++ b/common/common-data-access/pom.xml
@@ -0,0 +1,27 @@
+
+
+
+ common
+ com.food.order
+ 1.0-SNAPSHOT
+
+ 4.0.0
+
+ common-data-access
+
+
+
+
+ org.postgresql
+ postgresql
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-jpa
+
+
+
+
\ No newline at end of file
diff --git a/order-service/order-data-access/src/main/java/com/food/order/system/data/access/restaurant/entity/RestaurantEntity.java b/common/common-data-access/src/main/java/com/food/order/system/common/data/access/entity/RestaurantEntity.java
similarity index 92%
rename from order-service/order-data-access/src/main/java/com/food/order/system/data/access/restaurant/entity/RestaurantEntity.java
rename to common/common-data-access/src/main/java/com/food/order/system/common/data/access/entity/RestaurantEntity.java
index b3d73d8..9a66f30 100644
--- a/order-service/order-data-access/src/main/java/com/food/order/system/data/access/restaurant/entity/RestaurantEntity.java
+++ b/common/common-data-access/src/main/java/com/food/order/system/common/data/access/entity/RestaurantEntity.java
@@ -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;
diff --git a/order-service/order-data-access/src/main/java/com/food/order/system/data/access/restaurant/entity/RestaurantEntityId.java b/common/common-data-access/src/main/java/com/food/order/system/common/data/access/entity/RestaurantEntityId.java
similarity index 92%
rename from order-service/order-data-access/src/main/java/com/food/order/system/data/access/restaurant/entity/RestaurantEntityId.java
rename to common/common-data-access/src/main/java/com/food/order/system/common/data/access/entity/RestaurantEntityId.java
index 46cbac3..8e02036 100644
--- a/order-service/order-data-access/src/main/java/com/food/order/system/data/access/restaurant/entity/RestaurantEntityId.java
+++ b/common/common-data-access/src/main/java/com/food/order/system/common/data/access/entity/RestaurantEntityId.java
@@ -1,4 +1,4 @@
-package com.food.order.system.data.access.restaurant.entity;
+package com.food.order.system.common.data.access.entity;
import lombok.*;
diff --git a/order-service/order-data-access/src/main/java/com/food/order/system/data/access/restaurant/exception/RestaurantDataAccessException.java b/common/common-data-access/src/main/java/com/food/order/system/common/data/access/exception/RestaurantDataAccessException.java
similarity index 69%
rename from order-service/order-data-access/src/main/java/com/food/order/system/data/access/restaurant/exception/RestaurantDataAccessException.java
rename to common/common-data-access/src/main/java/com/food/order/system/common/data/access/exception/RestaurantDataAccessException.java
index 6220767..b802d2b 100644
--- a/order-service/order-data-access/src/main/java/com/food/order/system/data/access/restaurant/exception/RestaurantDataAccessException.java
+++ b/common/common-data-access/src/main/java/com/food/order/system/common/data/access/exception/RestaurantDataAccessException.java
@@ -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) {
diff --git a/order-service/order-data-access/src/main/java/com/food/order/system/data/access/restaurant/repository/RestaurantJpaRepository.java b/common/common-data-access/src/main/java/com/food/order/system/common/data/access/repository/RestaurantJpaRepository.java
similarity index 73%
rename from order-service/order-data-access/src/main/java/com/food/order/system/data/access/restaurant/repository/RestaurantJpaRepository.java
rename to common/common-data-access/src/main/java/com/food/order/system/common/data/access/repository/RestaurantJpaRepository.java
index def551d..a6c43d8 100644
--- a/order-service/order-data-access/src/main/java/com/food/order/system/data/access/restaurant/repository/RestaurantJpaRepository.java
+++ b/common/common-data-access/src/main/java/com/food/order/system/common/data/access/repository/RestaurantJpaRepository.java
@@ -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;
diff --git a/common/common-domain/src/main/java/com/food/order/sysyem/valueobject/RestaurantOrderStatus.java b/common/common-domain/src/main/java/com/food/order/sysyem/valueobject/RestaurantOrderStatus.java
new file mode 100644
index 0000000..d485e55
--- /dev/null
+++ b/common/common-domain/src/main/java/com/food/order/sysyem/valueobject/RestaurantOrderStatus.java
@@ -0,0 +1,5 @@
+package com.food.order.sysyem.valueobject;
+
+public enum RestaurantOrderStatus {
+ PAID
+}
diff --git a/common/pom.xml b/common/pom.xml
index 54296de..fb04f5d 100644
--- a/common/pom.xml
+++ b/common/pom.xml
@@ -14,6 +14,7 @@
common-domain
common-application
+ common-data-access
diff --git a/order-service/order-app/target/order-app-1.0-SNAPSHOT.jar b/order-service/order-app/target/order-app-1.0-SNAPSHOT.jar
index 29afa3d..df64f8b 100644
Binary files a/order-service/order-app/target/order-app-1.0-SNAPSHOT.jar and b/order-service/order-app/target/order-app-1.0-SNAPSHOT.jar differ
diff --git a/order-service/order-container/src/main/java/com/food/order/system/order/domain/OrderServiceApplication.java b/order-service/order-container/src/main/java/com/food/order/system/order/domain/OrderServiceApplication.java
index 533dc5b..8201a72 100644
--- a/order-service/order-container/src/main/java/com/food/order/system/order/domain/OrderServiceApplication.java
+++ b/order-service/order-container/src/main/java/com/food/order/system/order/domain/OrderServiceApplication.java
@@ -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) {
diff --git a/order-service/order-container/target/order-container-1.0-SNAPSHOT.jar b/order-service/order-container/target/order-container-1.0-SNAPSHOT.jar
index 6d54e88..b7db9a1 100644
Binary files a/order-service/order-container/target/order-container-1.0-SNAPSHOT.jar and b/order-service/order-container/target/order-container-1.0-SNAPSHOT.jar differ
diff --git a/order-service/order-data-access/pom.xml b/order-service/order-data-access/pom.xml
index f85e3e8..3977a06 100644
--- a/order-service/order-data-access/pom.xml
+++ b/order-service/order-data-access/pom.xml
@@ -29,6 +29,10 @@
org.postgresql
postgresql
+
+ com.food.order
+ common-data-access
+
\ No newline at end of file
diff --git a/order-service/order-data-access/src/main/java/com/food/order/system/data/access/restaurant/adapter/RestaurantRepositoryImpl.java b/order-service/order-data-access/src/main/java/com/food/order/system/data/access/restaurant/adapter/RestaurantRepositoryImpl.java
index c75db96..a6ea604 100644
--- a/order-service/order-data-access/src/main/java/com/food/order/system/data/access/restaurant/adapter/RestaurantRepositoryImpl.java
+++ b/order-service/order-data-access/src/main/java/com/food/order/system/data/access/restaurant/adapter/RestaurantRepositoryImpl.java
@@ -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;
diff --git a/order-service/order-data-access/src/main/java/com/food/order/system/data/access/restaurant/mapper/RestaurantDataAccessMapper.java b/order-service/order-data-access/src/main/java/com/food/order/system/data/access/restaurant/mapper/RestaurantDataAccessMapper.java
index 5b53fbc..1d29e8f 100644
--- a/order-service/order-data-access/src/main/java/com/food/order/system/data/access/restaurant/mapper/RestaurantDataAccessMapper.java
+++ b/order-service/order-data-access/src/main/java/com/food/order/system/data/access/restaurant/mapper/RestaurantDataAccessMapper.java
@@ -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;
diff --git a/order-service/order-data-access/target/order-data-access-1.0-SNAPSHOT.jar b/order-service/order-data-access/target/order-data-access-1.0-SNAPSHOT.jar
index dea858b..4a0c680 100644
Binary files a/order-service/order-data-access/target/order-data-access-1.0-SNAPSHOT.jar and b/order-service/order-data-access/target/order-data-access-1.0-SNAPSHOT.jar differ
diff --git a/order-service/order-domain/order-application-service/src/main/java/com/food/order/sysyem/ports/output/message/publisher/restaurantapproval/OrderPaidRestaurantRequestMessagePublisher.java b/order-service/order-domain/order-application-service/src/main/java/com/food/order/sysyem/ports/output/message/publisher/restaurantapproval/OrderPaidRestaurantRequestMessagePublisher.java
new file mode 100644
index 0000000..1d03f3f
--- /dev/null
+++ b/order-service/order-domain/order-application-service/src/main/java/com/food/order/sysyem/ports/output/message/publisher/restaurantapproval/OrderPaidRestaurantRequestMessagePublisher.java
@@ -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 {
+
+}
diff --git a/order-service/order-messaging/target/order-messaging-1.0-SNAPSHOT.jar b/order-service/order-messaging/target/order-messaging-1.0-SNAPSHOT.jar
index daa6533..10c57a6 100644
Binary files a/order-service/order-messaging/target/order-messaging-1.0-SNAPSHOT.jar and b/order-service/order-messaging/target/order-messaging-1.0-SNAPSHOT.jar differ
diff --git a/payment-service/payment-domain/payment-application-service/pom.xml b/payment-service/payment-domain/payment-application-service/pom.xml
index ea2f151..e599691 100644
--- a/payment-service/payment-domain/payment-application-service/pom.xml
+++ b/payment-service/payment-domain/payment-application-service/pom.xml
@@ -13,10 +13,6 @@
-
- com.food.order
- payment-domain
-
com.food.order
@@ -32,11 +28,10 @@
org.springframework
spring-tx
+
com.food.order
payment-domain-core
- 1.0-SNAPSHOT
- compile
diff --git a/pom.xml b/pom.xml
index bf3e86b..8ea78e5 100644
--- a/pom.xml
+++ b/pom.xml
@@ -16,6 +16,7 @@
infrastructure/kafka
customer-service
payment-service
+ restaurant-service
@@ -103,6 +104,43 @@
${project.version}
+
+ com.food.order
+ restaurant-application-service
+ ${project.version}
+
+
+
+ com.food.order
+ common-data-access
+ ${project.version}
+
+
+
+ com.food.order
+ restaurant-dataaccess
+ ${project.version}
+
+
+ com.food.order
+ restaurant-messaging
+ ${project.version}
+
+
+
+ com.food.order
+ restaurant-core-domain
+ ${project.version}
+
+
+
+
+ com.food.order
+ restaurant-domain
+ ${project.version}
+
+
+
com.food.order
kafka-consumer
diff --git a/restaurant-service/pom.xml b/restaurant-service/pom.xml
new file mode 100644
index 0000000..f61677e
--- /dev/null
+++ b/restaurant-service/pom.xml
@@ -0,0 +1,22 @@
+
+
+
+ food-ordering-system
+ com.food.order
+ 1.0-SNAPSHOT
+
+ 4.0.0
+
+ restaurant-service
+ pom
+
+ restaurant-domain
+ restaurant-messaging
+ restaurant-container
+ restaurant-dataaccess
+
+
+
+
\ No newline at end of file
diff --git a/restaurant-service/restaurant-container/pom.xml b/restaurant-service/restaurant-container/pom.xml
new file mode 100644
index 0000000..4c68d02
--- /dev/null
+++ b/restaurant-service/restaurant-container/pom.xml
@@ -0,0 +1,61 @@
+
+
+
+ restaurant-service
+ com.food.order
+ 1.0-SNAPSHOT
+
+ 4.0.0
+
+ restaurant-container
+
+
+
+ com.food.order
+ restaurant-core-domain
+
+
+ com.food.order
+ restaurant-application-service
+
+
+ com.food.order
+ restaurant-dataaccess
+
+
+ com.food.order
+ restaurant-messaging
+
+
+ org.springframework.boot
+ spring-boot-starter
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+ ${project.groupId}/restaurant.service:${project.version}
+
+
+
+
+ install
+
+ build-image
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/restaurant-service/restaurant-container/src/main/java/com/food/order/system/restaurant/container/RestaurantBeanConfig.java b/restaurant-service/restaurant-container/src/main/java/com/food/order/system/restaurant/container/RestaurantBeanConfig.java
new file mode 100644
index 0000000..ef28de8
--- /dev/null
+++ b/restaurant-service/restaurant-container/src/main/java/com/food/order/system/restaurant/container/RestaurantBeanConfig.java
@@ -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();
+ }
+}
diff --git a/restaurant-service/restaurant-container/src/main/java/com/food/order/system/restaurant/container/RestaurantServiceApplication.java b/restaurant-service/restaurant-container/src/main/java/com/food/order/system/restaurant/container/RestaurantServiceApplication.java
new file mode 100644
index 0000000..a5de1ec
--- /dev/null
+++ b/restaurant-service/restaurant-container/src/main/java/com/food/order/system/restaurant/container/RestaurantServiceApplication.java
@@ -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);
+ }
+}
diff --git a/restaurant-service/restaurant-container/src/main/resources/application.yml b/restaurant-service/restaurant-container/src/main/resources/application.yml
new file mode 100644
index 0000000..8e36e2f
--- /dev/null
+++ b/restaurant-service/restaurant-container/src/main/resources/application.yml
@@ -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
\ No newline at end of file
diff --git a/restaurant-service/restaurant-container/src/main/resources/init-data.sql b/restaurant-service/restaurant-container/src/main/resources/init-data.sql
new file mode 100644
index 0000000..6311c69
--- /dev/null
+++ b/restaurant-service/restaurant-container/src/main/resources/init-data.sql
@@ -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');
diff --git a/restaurant-service/restaurant-container/src/main/resources/init-schema.sql b/restaurant-service/restaurant-container/src/main/resources/init-schema.sql
new file mode 100644
index 0000000..d14ba7a
--- /dev/null
+++ b/restaurant-service/restaurant-container/src/main/resources/init-schema.sql
@@ -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();
\ No newline at end of file
diff --git a/restaurant-service/restaurant-dataaccess/pom.xml b/restaurant-service/restaurant-dataaccess/pom.xml
new file mode 100644
index 0000000..0d8bc00
--- /dev/null
+++ b/restaurant-service/restaurant-dataaccess/pom.xml
@@ -0,0 +1,38 @@
+
+
+
+ restaurant-service
+ com.food.order
+ 1.0-SNAPSHOT
+
+ 4.0.0
+
+ restaurant-dataaccess
+
+
+
+
+
+ com.food.order
+ restaurant-application-service
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-jpa
+
+
+
+ org.postgresql
+ postgresql
+
+
+
+ com.food.order
+ common-data-access
+
+
+
+
\ No newline at end of file
diff --git a/restaurant-service/restaurant-dataaccess/src/main/java/com/food/order/system/data/access/restaurant/adapter/OrderApprovalRepositoryImpl.java b/restaurant-service/restaurant-dataaccess/src/main/java/com/food/order/system/data/access/restaurant/adapter/OrderApprovalRepositoryImpl.java
new file mode 100644
index 0000000..f2293ff
--- /dev/null
+++ b/restaurant-service/restaurant-dataaccess/src/main/java/com/food/order/system/data/access/restaurant/adapter/OrderApprovalRepositoryImpl.java
@@ -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)));
+ }
+
+}
diff --git a/restaurant-service/restaurant-dataaccess/src/main/java/com/food/order/system/data/access/restaurant/adapter/RestaurantRepositoryImpl.java b/restaurant-service/restaurant-dataaccess/src/main/java/com/food/order/system/data/access/restaurant/adapter/RestaurantRepositoryImpl.java
new file mode 100644
index 0000000..515ee9a
--- /dev/null
+++ b/restaurant-service/restaurant-dataaccess/src/main/java/com/food/order/system/data/access/restaurant/adapter/RestaurantRepositoryImpl.java
@@ -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 findRestaurantInformation(Restaurant restaurant) {
+ List restaurantProducts =
+ restaurantDataAccessMapper.restaurantToRestaurantProducts(restaurant);
+ Optional> restaurantEntities = restaurantJpaRepository
+ .findByRestaurantIdAndProductIdIn(restaurant.getId().getValue(),
+ restaurantProducts);
+ return restaurantEntities.map(restaurantDataAccessMapper::restaurantEntityToRestaurant);
+ }
+}
diff --git a/restaurant-service/restaurant-dataaccess/src/main/java/com/food/order/system/data/access/restaurant/entity/OrderApprovalEntity.java b/restaurant-service/restaurant-dataaccess/src/main/java/com/food/order/system/data/access/restaurant/entity/OrderApprovalEntity.java
new file mode 100644
index 0000000..faf4ea5
--- /dev/null
+++ b/restaurant-service/restaurant-dataaccess/src/main/java/com/food/order/system/data/access/restaurant/entity/OrderApprovalEntity.java
@@ -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;
+}
diff --git a/restaurant-service/restaurant-dataaccess/src/main/java/com/food/order/system/data/access/restaurant/mapper/RestaurantDataAccessMapper.java b/restaurant-service/restaurant-dataaccess/src/main/java/com/food/order/system/data/access/restaurant/mapper/RestaurantDataAccessMapper.java
new file mode 100644
index 0000000..732f5a4
--- /dev/null
+++ b/restaurant-service/restaurant-dataaccess/src/main/java/com/food/order/system/data/access/restaurant/mapper/RestaurantDataAccessMapper.java
@@ -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 restaurantToRestaurantProducts(Restaurant restaurant) {
+ return restaurant.getOrderDetail().getProducts().stream()
+ .map(product -> product.getId().getValue())
+ .toList();
+ }
+
+ public Restaurant restaurantEntityToRestaurant(List restaurantEntities) {
+ RestaurantEntity restaurantEntity =
+ restaurantEntities.stream().findFirst().orElseThrow(() ->
+ new RestaurantDataAccessException("No restaurants found!"));
+
+ List 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();
+ }
+
+}
diff --git a/restaurant-service/restaurant-dataaccess/src/main/java/com/food/order/system/data/access/restaurant/repository/OrderApprovalJpaRepository.java b/restaurant-service/restaurant-dataaccess/src/main/java/com/food/order/system/data/access/restaurant/repository/OrderApprovalJpaRepository.java
new file mode 100644
index 0000000..16cf40b
--- /dev/null
+++ b/restaurant-service/restaurant-dataaccess/src/main/java/com/food/order/system/data/access/restaurant/repository/OrderApprovalJpaRepository.java
@@ -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 {
+
+
+}
diff --git a/restaurant-service/restaurant-domain/pom.xml b/restaurant-service/restaurant-domain/pom.xml
new file mode 100644
index 0000000..3bce511
--- /dev/null
+++ b/restaurant-service/restaurant-domain/pom.xml
@@ -0,0 +1,22 @@
+
+
+
+ restaurant-service
+ com.food.order
+ 1.0-SNAPSHOT
+
+ 4.0.0
+ restaurant-domain
+ pom
+
+
+ restaurant-core-domain
+ restaurant-application-service
+
+
+
+
+
+
\ No newline at end of file
diff --git a/restaurant-service/restaurant-domain/restaurant-application-service/pom.xml b/restaurant-service/restaurant-domain/restaurant-application-service/pom.xml
new file mode 100644
index 0000000..8a10a47
--- /dev/null
+++ b/restaurant-service/restaurant-domain/restaurant-application-service/pom.xml
@@ -0,0 +1,39 @@
+
+
+
+ restaurant-domain
+ com.food.order
+ 1.0-SNAPSHOT
+ ../pom.xml
+
+ 4.0.0
+
+ restaurant-application-service
+
+
+
+
+ com.food.order
+ restaurant-core-domain
+
+
+
+ org.springframework.boot
+ spring-boot-starter-validation
+
+
+
+ com.food.order
+ common-domain
+
+
+
+ org.springframework
+ spring-tx
+
+
+
+
+
\ No newline at end of file
diff --git a/restaurant-service/restaurant-domain/restaurant-application-service/src/main/java/com/food/ordery/system/restaurant/domain/service/RestaurantApprovalRequestHelper.java b/restaurant-service/restaurant-domain/restaurant-application-service/src/main/java/com/food/ordery/system/restaurant/domain/service/RestaurantApprovalRequestHelper.java
new file mode 100644
index 0000000..11f8786
--- /dev/null
+++ b/restaurant-service/restaurant-domain/restaurant-application-service/src/main/java/com/food/ordery/system/restaurant/domain/service/RestaurantApprovalRequestHelper.java
@@ -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 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;
+ }
+}
diff --git a/restaurant-service/restaurant-domain/restaurant-application-service/src/main/java/com/food/ordery/system/restaurant/domain/service/RestaurantApprovalRequestMessageListenerImpl.java b/restaurant-service/restaurant-domain/restaurant-application-service/src/main/java/com/food/ordery/system/restaurant/domain/service/RestaurantApprovalRequestMessageListenerImpl.java
new file mode 100644
index 0000000..4b58fa5
--- /dev/null
+++ b/restaurant-service/restaurant-domain/restaurant-application-service/src/main/java/com/food/ordery/system/restaurant/domain/service/RestaurantApprovalRequestMessageListenerImpl.java
@@ -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();
+ }
+}
diff --git a/restaurant-service/restaurant-domain/restaurant-application-service/src/main/java/com/food/ordery/system/restaurant/domain/service/config/RestaurantServiceConfig.java b/restaurant-service/restaurant-domain/restaurant-application-service/src/main/java/com/food/ordery/system/restaurant/domain/service/config/RestaurantServiceConfig.java
new file mode 100644
index 0000000..320fff1
--- /dev/null
+++ b/restaurant-service/restaurant-domain/restaurant-application-service/src/main/java/com/food/ordery/system/restaurant/domain/service/config/RestaurantServiceConfig.java
@@ -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;
+
+}
diff --git a/restaurant-service/restaurant-domain/restaurant-application-service/src/main/java/com/food/ordery/system/restaurant/domain/service/dto/RestaurantApprovalRequest.java b/restaurant-service/restaurant-domain/restaurant-application-service/src/main/java/com/food/ordery/system/restaurant/domain/service/dto/RestaurantApprovalRequest.java
new file mode 100644
index 0000000..b0afe0e
--- /dev/null
+++ b/restaurant-service/restaurant-domain/restaurant-application-service/src/main/java/com/food/ordery/system/restaurant/domain/service/dto/RestaurantApprovalRequest.java
@@ -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 products;
+ private BigDecimal price;
+ private Instant createdAt;
+}
diff --git a/restaurant-service/restaurant-domain/restaurant-application-service/src/main/java/com/food/ordery/system/restaurant/domain/service/exception/RestaurantApplicationServiceException.java b/restaurant-service/restaurant-domain/restaurant-application-service/src/main/java/com/food/ordery/system/restaurant/domain/service/exception/RestaurantApplicationServiceException.java
new file mode 100644
index 0000000..6816abc
--- /dev/null
+++ b/restaurant-service/restaurant-domain/restaurant-application-service/src/main/java/com/food/ordery/system/restaurant/domain/service/exception/RestaurantApplicationServiceException.java
@@ -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);
+ }
+}
diff --git a/restaurant-service/restaurant-domain/restaurant-application-service/src/main/java/com/food/ordery/system/restaurant/domain/service/mapper/RestaurantDataMapper.java b/restaurant-service/restaurant-domain/restaurant-application-service/src/main/java/com/food/ordery/system/restaurant/domain/service/mapper/RestaurantDataMapper.java
new file mode 100644
index 0000000..727e0de
--- /dev/null
+++ b/restaurant-service/restaurant-domain/restaurant-application-service/src/main/java/com/food/ordery/system/restaurant/domain/service/mapper/RestaurantDataMapper.java
@@ -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();
+ }
+}
diff --git a/restaurant-service/restaurant-domain/restaurant-application-service/src/main/java/com/food/ordery/system/restaurant/domain/service/ports/input/message/listener/RestaurantApprovalRequestMessageListener.java b/restaurant-service/restaurant-domain/restaurant-application-service/src/main/java/com/food/ordery/system/restaurant/domain/service/ports/input/message/listener/RestaurantApprovalRequestMessageListener.java
new file mode 100644
index 0000000..4b72ecd
--- /dev/null
+++ b/restaurant-service/restaurant-domain/restaurant-application-service/src/main/java/com/food/ordery/system/restaurant/domain/service/ports/input/message/listener/RestaurantApprovalRequestMessageListener.java
@@ -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);
+}
diff --git a/restaurant-service/restaurant-domain/restaurant-application-service/src/main/java/com/food/ordery/system/restaurant/domain/service/ports/output/message/publisher/OrderApprovedMessagePublisher.java b/restaurant-service/restaurant-domain/restaurant-application-service/src/main/java/com/food/ordery/system/restaurant/domain/service/ports/output/message/publisher/OrderApprovedMessagePublisher.java
new file mode 100644
index 0000000..80c5962
--- /dev/null
+++ b/restaurant-service/restaurant-domain/restaurant-application-service/src/main/java/com/food/ordery/system/restaurant/domain/service/ports/output/message/publisher/OrderApprovedMessagePublisher.java
@@ -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 {
+
+}
diff --git a/restaurant-service/restaurant-domain/restaurant-application-service/src/main/java/com/food/ordery/system/restaurant/domain/service/ports/output/message/publisher/OrderRejectedMessagePublisher.java b/restaurant-service/restaurant-domain/restaurant-application-service/src/main/java/com/food/ordery/system/restaurant/domain/service/ports/output/message/publisher/OrderRejectedMessagePublisher.java
new file mode 100644
index 0000000..2878ce6
--- /dev/null
+++ b/restaurant-service/restaurant-domain/restaurant-application-service/src/main/java/com/food/ordery/system/restaurant/domain/service/ports/output/message/publisher/OrderRejectedMessagePublisher.java
@@ -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 {
+
+}
diff --git a/restaurant-service/restaurant-domain/restaurant-application-service/src/main/java/com/food/ordery/system/restaurant/domain/service/ports/output/repository/OrderApprovalRepository.java b/restaurant-service/restaurant-domain/restaurant-application-service/src/main/java/com/food/ordery/system/restaurant/domain/service/ports/output/repository/OrderApprovalRepository.java
new file mode 100644
index 0000000..e897f1d
--- /dev/null
+++ b/restaurant-service/restaurant-domain/restaurant-application-service/src/main/java/com/food/ordery/system/restaurant/domain/service/ports/output/repository/OrderApprovalRepository.java
@@ -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);
+}
diff --git a/restaurant-service/restaurant-domain/restaurant-application-service/src/main/java/com/food/ordery/system/restaurant/domain/service/ports/output/repository/RestaurantRepository.java b/restaurant-service/restaurant-domain/restaurant-application-service/src/main/java/com/food/ordery/system/restaurant/domain/service/ports/output/repository/RestaurantRepository.java
new file mode 100644
index 0000000..8ca9da5
--- /dev/null
+++ b/restaurant-service/restaurant-domain/restaurant-application-service/src/main/java/com/food/ordery/system/restaurant/domain/service/ports/output/repository/RestaurantRepository.java
@@ -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 findRestaurantInformation(Restaurant restaurant);
+
+}
diff --git a/restaurant-service/restaurant-domain/restaurant-core-domain/pom.xml b/restaurant-service/restaurant-domain/restaurant-core-domain/pom.xml
new file mode 100644
index 0000000..27ba0ca
--- /dev/null
+++ b/restaurant-service/restaurant-domain/restaurant-core-domain/pom.xml
@@ -0,0 +1,22 @@
+
+
+
+ restaurant-domain
+ com.food.order
+ 1.0-SNAPSHOT
+
+ 4.0.0
+
+ restaurant-core-domain
+
+
+
+ com.food.order
+ common-domain
+
+
+
+
+
\ No newline at end of file
diff --git a/restaurant-service/restaurant-domain/restaurant-core-domain/src/main/java/com/food/order/system/restaurant/domain/core/RestaurantDomainService.java b/restaurant-service/restaurant-domain/restaurant-core-domain/src/main/java/com/food/order/system/restaurant/domain/core/RestaurantDomainService.java
new file mode 100644
index 0000000..7ec250f
--- /dev/null
+++ b/restaurant-service/restaurant-domain/restaurant-core-domain/src/main/java/com/food/order/system/restaurant/domain/core/RestaurantDomainService.java
@@ -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 failureMessages,
+ DomainEventPublisher publisher,
+ DomainEventPublisher rejectedPublisher);
+
+}
diff --git a/restaurant-service/restaurant-domain/restaurant-core-domain/src/main/java/com/food/order/system/restaurant/domain/core/RestaurantDomainServiceImpl.java b/restaurant-service/restaurant-domain/restaurant-core-domain/src/main/java/com/food/order/system/restaurant/domain/core/RestaurantDomainServiceImpl.java
new file mode 100644
index 0000000..8559162
--- /dev/null
+++ b/restaurant-service/restaurant-domain/restaurant-core-domain/src/main/java/com/food/order/system/restaurant/domain/core/RestaurantDomainServiceImpl.java
@@ -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 failureMessages,
+ DomainEventPublisher publisher,
+ DomainEventPublisher 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);
+ }
+
+ }
+}
diff --git a/restaurant-service/restaurant-domain/restaurant-core-domain/src/main/java/com/food/order/system/restaurant/domain/core/entity/OrderApproval.java b/restaurant-service/restaurant-domain/restaurant-core-domain/src/main/java/com/food/order/system/restaurant/domain/core/entity/OrderApproval.java
new file mode 100644
index 0000000..79416d9
--- /dev/null
+++ b/restaurant-service/restaurant-domain/restaurant-core-domain/src/main/java/com/food/order/system/restaurant/domain/core/entity/OrderApproval.java
@@ -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 {
+
+ 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);
+ }
+ }
+}
diff --git a/restaurant-service/restaurant-domain/restaurant-core-domain/src/main/java/com/food/order/system/restaurant/domain/core/entity/OrderDetail.java b/restaurant-service/restaurant-domain/restaurant-core-domain/src/main/java/com/food/order/system/restaurant/domain/core/entity/OrderDetail.java
new file mode 100644
index 0000000..a8831e4
--- /dev/null
+++ b/restaurant-service/restaurant-domain/restaurant-core-domain/src/main/java/com/food/order/system/restaurant/domain/core/entity/OrderDetail.java
@@ -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 {
+ private OrderStatus status;
+ private Money totalAmount;
+ private final List 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 getProducts() {
+ return products;
+ }
+
+
+ public static final class Builder {
+ private OrderId orderId;
+ private OrderStatus status;
+ private Money totalAmount;
+ private List 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 val) {
+ products = val;
+ return this;
+ }
+
+ public OrderDetail build() {
+ return new OrderDetail(this);
+ }
+ }
+}
diff --git a/restaurant-service/restaurant-domain/restaurant-core-domain/src/main/java/com/food/order/system/restaurant/domain/core/entity/Product.java b/restaurant-service/restaurant-domain/restaurant-core-domain/src/main/java/com/food/order/system/restaurant/domain/core/entity/Product.java
new file mode 100644
index 0000000..c997d06
--- /dev/null
+++ b/restaurant-service/restaurant-domain/restaurant-core-domain/src/main/java/com/food/order/system/restaurant/domain/core/entity/Product.java
@@ -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 {
+
+ 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);
+ }
+ }
+}
diff --git a/restaurant-service/restaurant-domain/restaurant-core-domain/src/main/java/com/food/order/system/restaurant/domain/core/entity/Restaurant.java b/restaurant-service/restaurant-domain/restaurant-core-domain/src/main/java/com/food/order/system/restaurant/domain/core/entity/Restaurant.java
new file mode 100644
index 0000000..050bf9d
--- /dev/null
+++ b/restaurant-service/restaurant-domain/restaurant-core-domain/src/main/java/com/food/order/system/restaurant/domain/core/entity/Restaurant.java
@@ -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 {
+ private OrderApproval orderApproval;
+ private boolean active;
+ private final OrderDetail orderDetail;
+
+ public void validateOrder(List 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);
+ }
+ }
+}
diff --git a/restaurant-service/restaurant-domain/restaurant-core-domain/src/main/java/com/food/order/system/restaurant/domain/core/event/OrderApprovalEvent.java b/restaurant-service/restaurant-domain/restaurant-core-domain/src/main/java/com/food/order/system/restaurant/domain/core/event/OrderApprovalEvent.java
new file mode 100644
index 0000000..064e683
--- /dev/null
+++ b/restaurant-service/restaurant-domain/restaurant-core-domain/src/main/java/com/food/order/system/restaurant/domain/core/event/OrderApprovalEvent.java
@@ -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 {
+
+ private final OrderApproval orderApproval;
+ private final RestaurantId restaurantId;
+ private final List failureMessages;
+ private final ZonedDateTime createdAt;
+
+ public OrderApprovalEvent(OrderApproval orderApproval,
+ RestaurantId restaurantId,
+ List 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 getFailureMessages() {
+ return failureMessages;
+ }
+
+ public ZonedDateTime getCreatedAt() {
+ return createdAt;
+ }
+}
diff --git a/restaurant-service/restaurant-domain/restaurant-core-domain/src/main/java/com/food/order/system/restaurant/domain/core/event/OrderApprovedEvent.java b/restaurant-service/restaurant-domain/restaurant-core-domain/src/main/java/com/food/order/system/restaurant/domain/core/event/OrderApprovedEvent.java
new file mode 100644
index 0000000..02baddc
--- /dev/null
+++ b/restaurant-service/restaurant-domain/restaurant-core-domain/src/main/java/com/food/order/system/restaurant/domain/core/event/OrderApprovedEvent.java
@@ -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 publisher;
+
+ public OrderApprovedEvent(OrderApproval orderApproval,
+ RestaurantId restaurantId,
+ List failureMessages,
+ ZonedDateTime createdAt,
+ DomainEventPublisher publisher) {
+ super(orderApproval, restaurantId, failureMessages, createdAt);
+ this.publisher = publisher;
+ }
+
+ @Override
+ public void fire() {
+ publisher.publish(this);
+ }
+}
diff --git a/restaurant-service/restaurant-domain/restaurant-core-domain/src/main/java/com/food/order/system/restaurant/domain/core/event/OrderRejectedEvent.java b/restaurant-service/restaurant-domain/restaurant-core-domain/src/main/java/com/food/order/system/restaurant/domain/core/event/OrderRejectedEvent.java
new file mode 100644
index 0000000..db850e5
--- /dev/null
+++ b/restaurant-service/restaurant-domain/restaurant-core-domain/src/main/java/com/food/order/system/restaurant/domain/core/event/OrderRejectedEvent.java
@@ -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 publisher;
+
+ public OrderRejectedEvent(OrderApproval orderApproval,
+ RestaurantId restaurantId,
+ List failureMessages,
+ ZonedDateTime createdAt,
+ DomainEventPublisher publisher) {
+ super(orderApproval, restaurantId, failureMessages, createdAt);
+ this.publisher = publisher;
+ }
+
+ @Override
+ public void fire() {
+ publisher.publish(this);
+ }
+}
diff --git a/restaurant-service/restaurant-domain/restaurant-core-domain/src/main/java/com/food/order/system/restaurant/domain/core/exception/RestaurantDomainException.java b/restaurant-service/restaurant-domain/restaurant-core-domain/src/main/java/com/food/order/system/restaurant/domain/core/exception/RestaurantDomainException.java
new file mode 100644
index 0000000..c4d8ea3
--- /dev/null
+++ b/restaurant-service/restaurant-domain/restaurant-core-domain/src/main/java/com/food/order/system/restaurant/domain/core/exception/RestaurantDomainException.java
@@ -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);
+ }
+}
diff --git a/restaurant-service/restaurant-domain/restaurant-core-domain/src/main/java/com/food/order/system/restaurant/domain/core/exception/RestaurantNotFoundException.java b/restaurant-service/restaurant-domain/restaurant-core-domain/src/main/java/com/food/order/system/restaurant/domain/core/exception/RestaurantNotFoundException.java
new file mode 100644
index 0000000..39edb1e
--- /dev/null
+++ b/restaurant-service/restaurant-domain/restaurant-core-domain/src/main/java/com/food/order/system/restaurant/domain/core/exception/RestaurantNotFoundException.java
@@ -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);
+ }
+}
diff --git a/restaurant-service/restaurant-domain/restaurant-core-domain/src/main/java/com/food/order/system/restaurant/domain/core/valueobject/OrderApprovalId.java b/restaurant-service/restaurant-domain/restaurant-core-domain/src/main/java/com/food/order/system/restaurant/domain/core/valueobject/OrderApprovalId.java
new file mode 100644
index 0000000..08a77d1
--- /dev/null
+++ b/restaurant-service/restaurant-domain/restaurant-core-domain/src/main/java/com/food/order/system/restaurant/domain/core/valueobject/OrderApprovalId.java
@@ -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 {
+ public OrderApprovalId(UUID value) {
+ super(value);
+ }
+}
diff --git a/restaurant-service/restaurant-messaging/pom.xml b/restaurant-service/restaurant-messaging/pom.xml
new file mode 100644
index 0000000..6259b28
--- /dev/null
+++ b/restaurant-service/restaurant-messaging/pom.xml
@@ -0,0 +1,35 @@
+
+
+
+ restaurant-service
+ com.food.order
+ 1.0-SNAPSHOT
+
+ 4.0.0
+
+ restaurant-messaging
+
+
+
+ com.food.order
+ restaurant-application-service
+
+
+
+ com.food.order
+ kafka-producer
+
+
+ com.food.order
+ kafka-consumer
+
+
+ com.food.order
+ kafka-model
+
+
+
+
+
\ No newline at end of file
diff --git a/restaurant-service/restaurant-messaging/src/main/java/com/food/order/system/restaurant/messaging/listener/kafka/RestaurantApprovalRequestKafkaListener.java b/restaurant-service/restaurant-messaging/src/main/java/com/food/order/system/restaurant/messaging/listener/kafka/RestaurantApprovalRequestKafkaListener.java
new file mode 100644
index 0000000..63ee9fc
--- /dev/null
+++ b/restaurant-service/restaurant-messaging/src/main/java/com/food/order/system/restaurant/messaging/listener/kafka/RestaurantApprovalRequestKafkaListener.java
@@ -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 {
+
+ 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 messages,
+ @Header(KafkaHeaders.RECEIVED_MESSAGE_KEY) List keys,
+ @Header(KafkaHeaders.RECEIVED_PARTITION_ID) List partitions,
+ @Header(KafkaHeaders.OFFSET) List 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));
+ });
+ }
+
+}
diff --git a/restaurant-service/restaurant-messaging/src/main/java/com/food/order/system/restaurant/messaging/mapper/RestaurantMessagingDataMapper.java b/restaurant-service/restaurant-messaging/src/main/java/com/food/order/system/restaurant/messaging/mapper/RestaurantMessagingDataMapper.java
new file mode 100644
index 0000000..0ca0da6
--- /dev/null
+++ b/restaurant-service/restaurant-messaging/src/main/java/com/food/order/system/restaurant/messaging/mapper/RestaurantMessagingDataMapper.java
@@ -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();
+ }
+}
diff --git a/restaurant-service/restaurant-messaging/src/main/java/com/food/order/system/restaurant/messaging/publisher/kafka/OrderApprovedKafkaMessagePublisher.java b/restaurant-service/restaurant-messaging/src/main/java/com/food/order/system/restaurant/messaging/publisher/kafka/OrderApprovedKafkaMessagePublisher.java
new file mode 100644
index 0000000..58451ec
--- /dev/null
+++ b/restaurant-service/restaurant-messaging/src/main/java/com/food/order/system/restaurant/messaging/publisher/kafka/OrderApprovedKafkaMessagePublisher.java
@@ -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 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());
+ }
+ }
+
+}
diff --git a/restaurant-service/restaurant-messaging/src/main/java/com/food/order/system/restaurant/messaging/publisher/kafka/OrderRejectedKafkaMessagePublisher.java b/restaurant-service/restaurant-messaging/src/main/java/com/food/order/system/restaurant/messaging/publisher/kafka/OrderRejectedKafkaMessagePublisher.java
new file mode 100644
index 0000000..adbb1e2
--- /dev/null
+++ b/restaurant-service/restaurant-messaging/src/main/java/com/food/order/system/restaurant/messaging/publisher/kafka/OrderRejectedKafkaMessagePublisher.java
@@ -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 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());
+ }
+ }
+
+}