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()); + } + } + +}