Implement SAGA Pattern commit and rollback.
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
package com.food.order.sysyem.event;
|
||||
|
||||
public final class EmptyEvent implements DomainEvent<Void> {
|
||||
|
||||
public static final EmptyEvent INSTANCE = new EmptyEvent();
|
||||
|
||||
private EmptyEvent() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fire() {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,10 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>infrastructure</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
<modules>
|
||||
<module>saga</module>
|
||||
</modules>
|
||||
|
||||
|
||||
</project>
|
||||
21
infrastructure/saga/pom.xml
Normal file
21
infrastructure/saga/pom.xml
Normal file
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>infrastructure</artifactId>
|
||||
<groupId>com.food.order</groupId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>saga</artifactId>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.food.order</groupId>
|
||||
<artifactId>common-domain</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.food.order.system.saga;
|
||||
|
||||
import com.food.order.sysyem.event.DomainEvent;
|
||||
|
||||
public interface SagaStep<T, S extends DomainEvent, U extends DomainEvent> {
|
||||
S process(T data);
|
||||
U rollback(T data);
|
||||
}
|
||||
@@ -10,6 +10,7 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@@ -26,6 +27,12 @@ public class OrderRepositoryImpl implements OrderRepository {
|
||||
.save(orderDataAccessMapper.orderToOrderEntity(order)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Order> findById(String orderId) {
|
||||
return orderJpaRepository.findById(UUID.fromString(orderId))
|
||||
.map(orderDataAccessMapper::orderEntityToOrder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Order> findByTrackingId(TrackingId trackingId) {
|
||||
return orderJpaRepository.findByTrackingId(trackingId.getValue())
|
||||
|
||||
@@ -36,6 +36,11 @@
|
||||
<artifactId>spring-tx</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.food.order</groupId>
|
||||
<artifactId>saga</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.food.order.sysyem;
|
||||
|
||||
import com.food.order.sysyem.dto.create.CreateOrderCommand;
|
||||
import com.food.order.sysyem.dto.create.CreateOrderResponse;
|
||||
import com.food.order.sysyem.helper.OrderCreateHelper;
|
||||
import com.food.order.sysyem.mapper.OrderDataMapper;
|
||||
import com.food.order.sysyem.ports.output.message.publisher.payment.OrderCreatedPaymentRequestMessagePublisher;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.food.order.sysyem;
|
||||
|
||||
import com.food.order.sysyem.dto.message.PaymentResponse;
|
||||
import com.food.order.sysyem.ports.input.message.listener.payment.PaymentResponseMessageListener;
|
||||
import com.food.order.sysyem.saga.OrderPaymentSaga;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
@@ -13,13 +14,18 @@ import org.springframework.validation.annotation.Validated;
|
||||
@RequiredArgsConstructor
|
||||
public class PaymentResponseMessageListenerImpl implements PaymentResponseMessageListener {
|
||||
|
||||
private final OrderPaymentSaga orderPaymentSaga;
|
||||
|
||||
@Override
|
||||
public void paymentCompleted(PaymentResponse paymentResponse) {
|
||||
|
||||
var paidEvent = orderPaymentSaga.process(paymentResponse);
|
||||
log.info("Payment completed for order with id: {}", paidEvent.getOrder().getId());
|
||||
paidEvent.fire();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paymentCancelled(PaymentResponse paymentResponse) {
|
||||
|
||||
orderPaymentSaga.rollback(paymentResponse);
|
||||
log.info("Payment cancelled for order with id: {}", paymentResponse.getOrderId());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.food.order.sysyem;
|
||||
|
||||
import com.food.order.sysyem.dto.message.RestaurantApprovalResponse;
|
||||
import com.food.order.sysyem.ports.input.message.listener.restaurantapproval.RestaurantApprovalResponseMessageListener;
|
||||
import com.food.order.sysyem.saga.OrderApprovalSaga;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
@@ -11,13 +12,18 @@ import org.springframework.stereotype.Service;
|
||||
@Service
|
||||
public class RestaurantApprovalResponseMessageListenerImpl implements RestaurantApprovalResponseMessageListener {
|
||||
|
||||
private final OrderApprovalSaga orderApprovalSaga;
|
||||
|
||||
@Override
|
||||
public void orderApproved(RestaurantApprovalResponse restaurantApprovalResponse) {
|
||||
|
||||
orderApprovalSaga.process(restaurantApprovalResponse);
|
||||
log.info("Order Approved: {}", restaurantApprovalResponse);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void orderRejected(RestaurantApprovalResponse restaurantApprovalResponse) {
|
||||
|
||||
var event = orderApprovalSaga.rollback(restaurantApprovalResponse);
|
||||
log.info("Order Rejected: {}", restaurantApprovalResponse);
|
||||
event.fire();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.food.order.sysyem;
|
||||
package com.food.order.sysyem.helper;
|
||||
|
||||
import com.food.order.sysyem.dto.create.CreateOrderCommand;
|
||||
import com.food.order.sysyem.event.publisher.DomainEventPublisher;
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.food.order.sysyem.helper;
|
||||
|
||||
import com.food.order.system.domain.entity.Order;
|
||||
import com.food.order.system.domain.exception.OrderNotFoundException;
|
||||
import com.food.order.sysyem.ports.output.repository.OrderRepository;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class OrderSagaHelper {
|
||||
|
||||
private final OrderRepository orderRepository;
|
||||
|
||||
public Order findOrder(String orderId) {
|
||||
return orderRepository.findById(orderId)
|
||||
.orElseThrow(() -> new OrderNotFoundException("Order not found -> Order id :" + orderId));
|
||||
}
|
||||
|
||||
public void saveOrder(Order order) {
|
||||
orderRepository.save(order);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -9,6 +9,8 @@ public interface OrderRepository {
|
||||
|
||||
Order save(Order order);
|
||||
|
||||
Optional<Order> findById(String trackingId);
|
||||
|
||||
Optional<Order> findByTrackingId(TrackingId trackingId);
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
package com.food.order.sysyem.saga;
|
||||
|
||||
import com.food.order.system.domain.event.OrderCancelledEvent;
|
||||
import com.food.order.system.domain.service.OrderDomainService;
|
||||
import com.food.order.system.saga.SagaStep;
|
||||
import com.food.order.sysyem.dto.message.RestaurantApprovalResponse;
|
||||
import com.food.order.sysyem.event.EmptyEvent;
|
||||
import com.food.order.sysyem.helper.OrderSagaHelper;
|
||||
import com.food.order.sysyem.ports.output.message.publisher.payment.OrderCancelledPaymentRequestMessagePublisher;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class OrderApprovalSaga implements SagaStep<RestaurantApprovalResponse, EmptyEvent, OrderCancelledEvent> {
|
||||
|
||||
private final OrderDomainService orderDomainService;
|
||||
private final OrderCancelledPaymentRequestMessagePublisher messagePublisher;
|
||||
private final OrderSagaHelper orderSagaHelper;
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public EmptyEvent process(RestaurantApprovalResponse data) {
|
||||
log.info("Approving order with id: {}", data.getOrderId());
|
||||
var order = orderSagaHelper.findOrder(data.getOrderId());
|
||||
orderDomainService.approve(order);
|
||||
orderSagaHelper.saveOrder(order);
|
||||
log.info("Order approved: {}", order);
|
||||
return EmptyEvent.INSTANCE;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public OrderCancelledEvent rollback(RestaurantApprovalResponse data) {
|
||||
log.info("Approving order with id: {}", data.getOrderId());
|
||||
var order = orderSagaHelper.findOrder(data.getOrderId());
|
||||
var cancelEvent = orderDomainService.cancelOrderPayment(order,data.getFailureMessages(),
|
||||
messagePublisher);
|
||||
orderSagaHelper.saveOrder(order);
|
||||
log.info("Order cancelled: {}", order);
|
||||
return cancelEvent;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package com.food.order.sysyem.saga;
|
||||
|
||||
import com.food.order.system.domain.event.OrderPaidEvent;
|
||||
import com.food.order.system.domain.service.OrderDomainService;
|
||||
import com.food.order.system.saga.SagaStep;
|
||||
import com.food.order.sysyem.dto.message.PaymentResponse;
|
||||
import com.food.order.sysyem.event.EmptyEvent;
|
||||
import com.food.order.sysyem.helper.OrderSagaHelper;
|
||||
import com.food.order.sysyem.ports.output.message.publisher.restaurantapproval.OrderPaidRestaurantRequestMessagePublisher;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class OrderPaymentSaga implements SagaStep<PaymentResponse, OrderPaidEvent, EmptyEvent> {
|
||||
|
||||
private final OrderDomainService orderDomainService;
|
||||
private final OrderSagaHelper orderSagaHelper;
|
||||
private final OrderPaidRestaurantRequestMessagePublisher orderPaidRestaurantRequestMessagePublisher;
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public OrderPaidEvent process(PaymentResponse data) {
|
||||
log.info("Completing payment for order with id: {}", data.getOrderId());
|
||||
var order = orderSagaHelper.findOrder(data.getOrderId());
|
||||
var paidEvent = orderDomainService.payOrder(order,orderPaidRestaurantRequestMessagePublisher);
|
||||
orderSagaHelper.saveOrder(order);
|
||||
log.info("Payment completed for order with id: {}", order.getId());
|
||||
return paidEvent;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public EmptyEvent rollback(PaymentResponse data) {
|
||||
log.info("Rolling back payment for order with id: {}", data.getOrderId());
|
||||
var order = orderSagaHelper.findOrder(data.getOrderId());
|
||||
orderDomainService.cancelOrder(order,data.getFailureMessages());
|
||||
orderSagaHelper.saveOrder(order);
|
||||
log.info("Payment rolled back for order with id: {}", order.getId());
|
||||
return EmptyEvent.INSTANCE;
|
||||
}
|
||||
}
|
||||
@@ -49,7 +49,7 @@ public class OrderMessagingDataMapper {
|
||||
.setRestaurantId(order.getRestaurantId().getValue().toString())
|
||||
.setProducts(order.getItems().stream()
|
||||
.map(item -> Product.newBuilder()
|
||||
.setId(item.getId().getValue().toString())
|
||||
.setId(item.getProduct().getId().getValue().toString())
|
||||
.setQuantity(item.getQuantity())
|
||||
.build())
|
||||
.toList())
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.food.order.system.payment.data.access.credithistory.adapter;
|
||||
|
||||
|
||||
import com.food.order.system.payment.application.service.ports.output.repository.CreditHistoryRepository;
|
||||
import com.food.order.system.payment.data.access.credithistory.entity.CreditHistoryEntity;
|
||||
import com.food.order.system.payment.data.access.credithistory.mapper.CreditHistoryDataAccessMapper;
|
||||
import com.food.order.system.payment.data.access.credithistory.repository.CreditHistoryJpaRepository;
|
||||
import com.food.order.system.payment.service.domain.entity.CreditHistory;
|
||||
@@ -10,6 +11,7 @@ import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Component
|
||||
public class CreditHistoryRepositoryImpl implements CreditHistoryRepository {
|
||||
@@ -29,13 +31,15 @@ public class CreditHistoryRepositoryImpl implements CreditHistoryRepository {
|
||||
.save(creditHistoryDataAccessMapper.creditHistoryToCreditHistoryEntity(creditHistory)));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Optional<List<CreditHistory>> findByCustomerId(CustomerId customerId) {
|
||||
return creditHistoryJpaRepository.findByCustomerId(customerId.getValue())
|
||||
Optional<List<CreditHistoryEntity>> creditHistory =
|
||||
creditHistoryJpaRepository.findByCustomerId(customerId.getValue());
|
||||
return creditHistory
|
||||
.map(creditHistoryList ->
|
||||
creditHistoryList.stream()
|
||||
.map(creditHistoryDataAccessMapper::creditHistoryEntityToCreditHistory)
|
||||
.toList());
|
||||
|
||||
.collect(Collectors.toList()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,7 +100,9 @@ public class PaymentDomainServiceImpl implements PaymentDomainService {
|
||||
.reduce(Money.ZERO, Money::add);
|
||||
}
|
||||
|
||||
private void updateCreditHistory(Payment payment, List<CreditHistory> creditHistory, TransactionType transactionType) {
|
||||
private void updateCreditHistory(Payment payment,
|
||||
List<CreditHistory> creditHistory,
|
||||
TransactionType transactionType) {
|
||||
creditHistory.add(
|
||||
CreditHistory.builder()
|
||||
.id(new CreditHistoryId(UUID.randomUUID()))
|
||||
|
||||
7
pom.xml
7
pom.xml
@@ -61,6 +61,13 @@
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.food.order</groupId>
|
||||
<artifactId>saga</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>com.food.order</groupId>
|
||||
<artifactId>payment-domain-core</artifactId>
|
||||
|
||||
@@ -6,10 +6,10 @@ import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
public class RestaurantBeanConfig {
|
||||
public class BeanConfiguration {
|
||||
|
||||
@Bean
|
||||
public RestaurantDomainService restaurantService() {
|
||||
public RestaurantDomainService restaurantDomainService() {
|
||||
return new RestaurantDomainServiceImpl();
|
||||
}
|
||||
}
|
||||
@@ -75,7 +75,8 @@ AS
|
||||
p.id AS product_id,
|
||||
p.name AS product_name,
|
||||
p.price AS product_price,
|
||||
p.available AS product_available
|
||||
p.available AS product_available,
|
||||
r.active AS product_active
|
||||
FROM restaurant.restaurants r,
|
||||
restaurant.products p,
|
||||
restaurant.restaurant_products rp
|
||||
|
||||
@@ -3,7 +3,7 @@ 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 com.food.order.system.restaurant.domain.service.ports.output.repository.OrderApprovalRepository;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ 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 com.food.order.system.restaurant.domain.service.ports.output.repository.RestaurantRepository;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
|
||||
@@ -16,7 +16,6 @@ import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Component
|
||||
public class RestaurantDataAccessMapper {
|
||||
@@ -39,7 +38,7 @@ public class RestaurantDataAccessMapper {
|
||||
.price(new Money(entity.getProductPrice()))
|
||||
.available(entity.getProductActive())
|
||||
.build())
|
||||
.collect(Collectors.toList());
|
||||
.toList();
|
||||
|
||||
return Restaurant.builder()
|
||||
.restaurantId(new RestaurantId(restaurantEntity.getRestaurantId()))
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
package com.food.order.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.system.restaurant.domain.service.dto.RestaurantApprovalRequest;
|
||||
import com.food.order.system.restaurant.domain.service.mapper.RestaurantDataMapper;
|
||||
import com.food.order.system.restaurant.domain.service.ports.output.message.publisher.OrderApprovedMessagePublisher;
|
||||
import com.food.order.system.restaurant.domain.service.ports.output.message.publisher.OrderRejectedMessagePublisher;
|
||||
import com.food.order.system.restaurant.domain.service.ports.output.repository.OrderApprovalRepository;
|
||||
import com.food.order.system.restaurant.domain.service.ports.output.repository.RestaurantRepository;
|
||||
import com.food.order.sysyem.valueobject.OrderId;
|
||||
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.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
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;
|
||||
|
||||
public RestaurantApprovalRequestHelper(RestaurantDomainService restaurantDomainService,
|
||||
RestaurantDataMapper restaurantDataMapper,
|
||||
RestaurantRepository restaurantRepository,
|
||||
OrderApprovalRepository orderApprovalRepository,
|
||||
OrderApprovedMessagePublisher orderApprovedMessagePublisher,
|
||||
OrderRejectedMessagePublisher orderRejectedMessagePublisher) {
|
||||
this.restaurantDomainService = restaurantDomainService;
|
||||
this.restaurantDataMapper = restaurantDataMapper;
|
||||
this.restaurantRepository = restaurantRepository;
|
||||
this.orderApprovalRepository = orderApprovalRepository;
|
||||
this.orderApprovedMessagePublisher = orderApprovedMessagePublisher;
|
||||
this.orderRejectedMessagePublisher = orderRejectedMessagePublisher;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public OrderApprovalEvent persistOrderApproval(RestaurantApprovalRequest request) {
|
||||
log.info("Persisting order approval request: {}", request);
|
||||
List<String> failureMessages = new ArrayList<>();
|
||||
var restaurant = findRestaurant(request);
|
||||
var event = restaurantDomainService.validateOrder
|
||||
(restaurant, failureMessages, orderApprovedMessagePublisher, orderRejectedMessagePublisher);
|
||||
|
||||
orderApprovalRepository.save(restaurant.getOrderApproval());
|
||||
return event;
|
||||
|
||||
}
|
||||
|
||||
private Restaurant findRestaurant(RestaurantApprovalRequest restaurantApprovalRequest) {
|
||||
Restaurant restaurant = restaurantDataMapper
|
||||
.restaurantApprovalRequestToRestaurant(restaurantApprovalRequest);
|
||||
Optional<Restaurant> restaurantResult = restaurantRepository.findRestaurantInformation(restaurant);
|
||||
if (restaurantResult.isEmpty()) {
|
||||
log.error("Restaurant with id " + restaurant.getId().getValue() + " not found!");
|
||||
throw new RestaurantNotFoundException("Restaurant with id " + restaurant.getId().getValue() +
|
||||
" not found!");
|
||||
}
|
||||
|
||||
Restaurant restaurantEntity = restaurantResult.get();
|
||||
restaurant.setActive(restaurantEntity.isActive());
|
||||
restaurant.getOrderDetail().getProducts().forEach(product ->
|
||||
restaurantEntity.getOrderDetail().getProducts().forEach(p -> {
|
||||
if (p.getId().equals(product.getId())) {
|
||||
product.updateWithConfirmedNamePriceAndAvailablity(p.getName(), p.getPrice(), p.isAvailable());
|
||||
}
|
||||
}));
|
||||
restaurant.getOrderDetail().setId(new OrderId(UUID.fromString(restaurantApprovalRequest.getOrderId())));
|
||||
|
||||
return restaurant;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.food.ordery.system.restaurant.domain.service;
|
||||
package com.food.order.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 com.food.order.system.restaurant.domain.service.dto.RestaurantApprovalRequest;
|
||||
import com.food.order.system.restaurant.domain.service.ports.input.message.listener.RestaurantApprovalRequestMessageListener;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
@@ -10,7 +10,6 @@ import org.springframework.stereotype.Service;
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class RestaurantApprovalRequestMessageListenerImpl implements RestaurantApprovalRequestMessageListener {
|
||||
|
||||
private final RestaurantApprovalRequestHelper restaurantApprovalRequestHelper;
|
||||
|
||||
@Override
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.food.ordery.system.restaurant.domain.service.config;
|
||||
package com.food.order.system.restaurant.domain.service.config;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
@@ -7,9 +7,7 @@ import org.springframework.context.annotation.Configuration;
|
||||
@Data
|
||||
@Configuration
|
||||
@ConfigurationProperties(prefix = "restaurant-service")
|
||||
public class RestaurantServiceConfig {
|
||||
|
||||
public class RestaurantServiceConfigData {
|
||||
private String restaurantApprovalRequestTopicName;
|
||||
private String restaurantApprovalResponseTopicName;
|
||||
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.food.ordery.system.restaurant.domain.service.dto;
|
||||
package com.food.order.system.restaurant.domain.service.dto;
|
||||
|
||||
import com.food.order.system.restaurant.domain.core.entity.Product;
|
||||
import com.food.order.sysyem.valueobject.RestaurantOrderStatus;
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.food.ordery.system.restaurant.domain.service.exception;
|
||||
package com.food.order.system.restaurant.domain.service.exception;
|
||||
|
||||
import com.food.order.sysyem.exception.DomainException;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.food.ordery.system.restaurant.domain.service.mapper;
|
||||
package com.food.order.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;
|
||||
@@ -7,7 +7,7 @@ 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 com.food.order.system.restaurant.domain.service.dto.RestaurantApprovalRequest;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.UUID;
|
||||
@@ -24,7 +24,6 @@ public class RestaurantDataMapper {
|
||||
product -> Product.builder()
|
||||
.productId(product.getId())
|
||||
.quantity(product.getQuantity())
|
||||
|
||||
.build()
|
||||
).toList())
|
||||
.totalAmount(new Money(request.getPrice()))
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.food.order.system.restaurant.domain.service.ports.input.message.listener;
|
||||
|
||||
import com.food.order.system.restaurant.domain.service.dto.RestaurantApprovalRequest;
|
||||
|
||||
public interface RestaurantApprovalRequestMessageListener {
|
||||
void approveOrder(RestaurantApprovalRequest restaurantApprovalRequest);
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
package com.food.ordery.system.restaurant.domain.service.ports.output.message.publisher;
|
||||
package com.food.order.system.restaurant.domain.service.ports.output.message.publisher;
|
||||
|
||||
import com.food.order.system.restaurant.domain.core.event.OrderApprovedEvent;
|
||||
import com.food.order.sysyem.event.publisher.DomainEventPublisher;
|
||||
|
||||
public interface OrderApprovedMessagePublisher extends DomainEventPublisher<OrderApprovedEvent> {
|
||||
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package com.food.ordery.system.restaurant.domain.service.ports.output.message.publisher;
|
||||
package com.food.order.system.restaurant.domain.service.ports.output.message.publisher;
|
||||
|
||||
import com.food.order.system.restaurant.domain.core.event.OrderRejectedEvent;
|
||||
import com.food.order.sysyem.event.publisher.DomainEventPublisher;
|
||||
|
||||
public interface OrderRejectedMessagePublisher extends DomainEventPublisher<OrderRejectedEvent> {
|
||||
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.food.ordery.system.restaurant.domain.service.ports.output.repository;
|
||||
package com.food.order.system.restaurant.domain.service.ports.output.repository;
|
||||
|
||||
import com.food.order.system.restaurant.domain.core.entity.OrderApproval;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.food.ordery.system.restaurant.domain.service.ports.output.repository;
|
||||
package com.food.order.system.restaurant.domain.service.ports.output.repository;
|
||||
|
||||
import com.food.order.system.restaurant.domain.core.entity.Restaurant;
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
package com.food.ordery.system.restaurant.domain.service;
|
||||
|
||||
import com.food.order.system.restaurant.domain.core.RestaurantDomainService;
|
||||
import com.food.order.system.restaurant.domain.core.entity.Restaurant;
|
||||
import com.food.order.system.restaurant.domain.core.event.OrderApprovalEvent;
|
||||
import com.food.order.system.restaurant.domain.core.exception.RestaurantNotFoundException;
|
||||
import com.food.order.sysyem.valueobject.OrderId;
|
||||
import com.food.ordery.system.restaurant.domain.service.dto.RestaurantApprovalRequest;
|
||||
import com.food.ordery.system.restaurant.domain.service.mapper.RestaurantDataMapper;
|
||||
import com.food.ordery.system.restaurant.domain.service.ports.output.message.publisher.OrderApprovedMessagePublisher;
|
||||
import com.food.ordery.system.restaurant.domain.service.ports.output.message.publisher.OrderRejectedMessagePublisher;
|
||||
import com.food.ordery.system.restaurant.domain.service.ports.output.repository.OrderApprovalRepository;
|
||||
import com.food.ordery.system.restaurant.domain.service.ports.output.repository.RestaurantRepository;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class RestaurantApprovalRequestHelper {
|
||||
|
||||
private final RestaurantDomainService restaurantDomainService;
|
||||
private final RestaurantDataMapper restaurantDataMapper;
|
||||
private final RestaurantRepository restaurantRepository;
|
||||
private final OrderApprovalRepository orderApprovalRepository;
|
||||
private final OrderApprovedMessagePublisher orderApprovedMessagePublisher;
|
||||
private final OrderRejectedMessagePublisher orderRejectedMessagePublisher;
|
||||
|
||||
@Transactional
|
||||
public OrderApprovalEvent persistOrderApproval(RestaurantApprovalRequest request) {
|
||||
log.info("Persisting order approval request: {}", request);
|
||||
List<String> failureMessages = new ArrayList<>();
|
||||
var restaurant = findRestaurant(request);
|
||||
var event = restaurantDomainService.validateOrder
|
||||
(restaurant, failureMessages, orderApprovedMessagePublisher, orderRejectedMessagePublisher);
|
||||
|
||||
orderApprovalRepository.save(restaurant.getOrderApproval());
|
||||
return event;
|
||||
|
||||
}
|
||||
|
||||
private Restaurant findRestaurant(RestaurantApprovalRequest request) {
|
||||
var restaurant = restaurantDataMapper.restaurantApprovalRequestToRestaurant(request);
|
||||
var resultRestaurant = restaurantRepository.findRestaurantInformation(restaurant).orElseThrow(
|
||||
() -> new RestaurantNotFoundException("Restaurant not found")
|
||||
);
|
||||
restaurant.setActive(resultRestaurant.isActive());
|
||||
restaurant.getOrderDetail().getProducts().forEach(product -> {
|
||||
resultRestaurant.getOrderDetail().getProducts().forEach(p -> {
|
||||
if (p.getId().equals(product.getId())) {
|
||||
p.updateWithConfirmedNamePriceAndAvailablity(p.getName(),p.getPrice(), p.isAvailable());
|
||||
}});
|
||||
});
|
||||
restaurant.getOrderDetail().setId(new OrderId(UUID.fromString(request.getOrderId())));
|
||||
return restaurant;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
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);
|
||||
}
|
||||
@@ -4,25 +4,28 @@ 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 com.food.order.system.restaurant.domain.service.ports.input.message.listener.RestaurantApprovalRequestMessageListener;
|
||||
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 org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
@Service
|
||||
public class RestaurantApprovalRequestKafkaListener implements KafkaConsumer<RestaurantApprovalRequestAvroModel> {
|
||||
|
||||
private final RestaurantApprovalRequestMessageListener restaurantApprovalRequestMessageListener;
|
||||
private final RestaurantMessagingDataMapper restaurantMessagingDataMapper;
|
||||
|
||||
public RestaurantApprovalRequestKafkaListener(RestaurantApprovalRequestMessageListener restaurantApprovalRequestMessageListener,
|
||||
RestaurantMessagingDataMapper restaurantMessagingDataMapper) {
|
||||
this.restaurantApprovalRequestMessageListener = restaurantApprovalRequestMessageListener;
|
||||
this.restaurantMessagingDataMapper = restaurantMessagingDataMapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
@KafkaListener(id = "${kafka-consumer-config.restaurant-approval-consumer-group-id}",
|
||||
|
||||
@@ -9,7 +9,7 @@ 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 com.food.order.system.restaurant.domain.service.dto.RestaurantApprovalRequest;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
@@ -6,8 +6,8 @@ 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 com.food.order.system.restaurant.domain.service.config.RestaurantServiceConfigData;
|
||||
import com.food.order.system.restaurant.domain.service.ports.output.message.publisher.OrderApprovedMessagePublisher;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
@@ -19,7 +19,7 @@ public class OrderApprovedKafkaMessagePublisher implements OrderApprovedMessageP
|
||||
|
||||
private final RestaurantMessagingDataMapper restaurantMessagingDataMapper;
|
||||
private final KafkaProducer<String, RestaurantApprovalResponseAvroModel> kafkaProducer;
|
||||
private final RestaurantServiceConfig restaurantServiceConfigData;
|
||||
private final RestaurantServiceConfigData restaurantServiceConfigData;
|
||||
private final KafkaMessageHelper kafkaMessageHelper;
|
||||
|
||||
|
||||
|
||||
@@ -6,8 +6,8 @@ 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 com.food.order.system.restaurant.domain.service.config.RestaurantServiceConfigData;
|
||||
import com.food.order.system.restaurant.domain.service.ports.output.message.publisher.OrderRejectedMessagePublisher;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
@@ -19,7 +19,7 @@ public class OrderRejectedKafkaMessagePublisher implements OrderRejectedMessageP
|
||||
|
||||
private final RestaurantMessagingDataMapper restaurantMessagingDataMapper;
|
||||
private final KafkaProducer<String, RestaurantApprovalResponseAvroModel> kafkaProducer;
|
||||
private final RestaurantServiceConfig restaurantServiceConfigData;
|
||||
private final RestaurantServiceConfigData restaurantServiceConfigData;
|
||||
private final KafkaMessageHelper kafkaMessageHelper;
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user