26
common/common-application/pom.xml
Normal file
26
common/common-application/pom.xml
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<parent>
|
||||||
|
<artifactId>common</artifactId>
|
||||||
|
<groupId>com.food.order</groupId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<artifactId>common-application</artifactId>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-validation</artifactId>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
</project>
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package com.food.order.system.application.handler;
|
||||||
|
|
||||||
|
import lombok.Builder;
|
||||||
|
|
||||||
|
@Builder
|
||||||
|
public record ErrorDTO(String code, String message) {
|
||||||
|
}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
package com.food.order.system.application.handler;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.web.bind.annotation.ControllerAdvice;
|
||||||
|
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||||
|
import org.springframework.web.bind.annotation.ResponseBody;
|
||||||
|
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||||
|
|
||||||
|
import javax.validation.ConstraintViolation;
|
||||||
|
import javax.validation.ConstraintViolationException;
|
||||||
|
import javax.validation.ValidationException;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@ControllerAdvice
|
||||||
|
public class GlobalExceptionHandler {
|
||||||
|
|
||||||
|
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
|
||||||
|
@ExceptionHandler(value = {Exception.class})
|
||||||
|
@ResponseBody
|
||||||
|
public ErrorDTO handleOrderDomainException(Exception e) {
|
||||||
|
log.error("Error occurred: {}", e.getMessage());
|
||||||
|
return ErrorDTO.builder()
|
||||||
|
.code(HttpStatus.INTERNAL_SERVER_ERROR.getReasonPhrase())
|
||||||
|
.message("Unknown error occurred")
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||||||
|
@ExceptionHandler(value = {ValidationException.class})
|
||||||
|
@ResponseBody
|
||||||
|
public ErrorDTO handleOrderDomainException(ValidationException e) {
|
||||||
|
ErrorDTO errorDTO;
|
||||||
|
if (e instanceof ConstraintViolationException) {
|
||||||
|
String violations = extractViolationsFromException((ConstraintViolationException) e);
|
||||||
|
log.error("Error occurred: {}", violations);
|
||||||
|
errorDTO = ErrorDTO.builder()
|
||||||
|
.code(HttpStatus.BAD_REQUEST.getReasonPhrase())
|
||||||
|
.message(violations)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
log.error("Error occurred: {}", e.getMessage());
|
||||||
|
errorDTO = ErrorDTO.builder()
|
||||||
|
.code(HttpStatus.BAD_REQUEST.getReasonPhrase())
|
||||||
|
.message(e.getMessage())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
return errorDTO;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String extractViolationsFromException(ConstraintViolationException e) {
|
||||||
|
return e.getConstraintViolations()
|
||||||
|
.stream()
|
||||||
|
.map(ConstraintViolation::getMessage)
|
||||||
|
.collect(Collectors.joining("->"));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -13,6 +13,7 @@
|
|||||||
<packaging>pom</packaging>
|
<packaging>pom</packaging>
|
||||||
<modules>
|
<modules>
|
||||||
<module>common-domain</module>
|
<module>common-domain</module>
|
||||||
|
<module>common-application</module>
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
|
|||||||
@@ -19,6 +19,21 @@
|
|||||||
<groupId>com.food.order</groupId>
|
<groupId>com.food.order</groupId>
|
||||||
<artifactId>order-application-service</artifactId>
|
<artifactId>order-application-service</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-validation</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.food.order</groupId>
|
||||||
|
<artifactId>common-application</artifactId>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
package com.food.order.system.service.app.api;
|
||||||
|
|
||||||
|
import com.food.order.domain.dto.create.CreateOrderCommand;
|
||||||
|
import com.food.order.domain.dto.create.CreateOrderResponse;
|
||||||
|
import com.food.order.domain.dto.track.TrackOrderQuery;
|
||||||
|
import com.food.order.domain.dto.track.TrackOrderResponse;
|
||||||
|
import com.food.order.domain.ports.input.service.OrderApplicationService;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
import org.springframework.web.context.annotation.RequestScope;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@CrossOrigin
|
||||||
|
@RequestScope
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@Slf4j
|
||||||
|
@Validated
|
||||||
|
@RequestMapping(value = "/api/orders", produces = "application/vnd.api.v1+json")
|
||||||
|
public class OrderController {
|
||||||
|
|
||||||
|
private final OrderApplicationService orderApplicationService;
|
||||||
|
|
||||||
|
@PostMapping
|
||||||
|
public ResponseEntity<CreateOrderResponse> createOrder(@RequestBody CreateOrderCommand createOrderCommand) {
|
||||||
|
log.info("Creating order with command: {}", createOrderCommand);
|
||||||
|
CreateOrderResponse createOrderResponse = orderApplicationService.createOrder(createOrderCommand);
|
||||||
|
log.info("Created order with tracking id: {}", createOrderResponse.orderTrackingId());
|
||||||
|
return ResponseEntity.ok(createOrderResponse);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/{orderTrackingId}")
|
||||||
|
public ResponseEntity<TrackOrderResponse> trackOrder(@PathVariable("orderTrackingId") UUID orderTrackingId) {
|
||||||
|
TrackOrderResponse trackOrderResponse = orderApplicationService.trackOrder
|
||||||
|
(new TrackOrderQuery(orderTrackingId));
|
||||||
|
log.info("Tracked order with tracking id: {}", orderTrackingId);
|
||||||
|
return ResponseEntity.ok(trackOrderResponse);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
package com.food.order.system.service.app.exception;
|
||||||
|
|
||||||
|
import com.food.order.system.application.handler.ErrorDTO;
|
||||||
|
import com.food.order.system.application.handler.GlobalExceptionHandler;
|
||||||
|
import com.food.order.system.domain.exception.OrderDomainException;
|
||||||
|
import com.food.order.system.domain.exception.OrderNotFoundException;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.web.bind.annotation.ControllerAdvice;
|
||||||
|
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||||
|
import org.springframework.web.bind.annotation.ResponseBody;
|
||||||
|
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||||
|
|
||||||
|
@ControllerAdvice
|
||||||
|
@Slf4j
|
||||||
|
public class OrderGlobalException extends GlobalExceptionHandler {
|
||||||
|
|
||||||
|
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||||||
|
@ExceptionHandler(value = {OrderDomainException.class})
|
||||||
|
@ResponseBody
|
||||||
|
public ErrorDTO handleOrderDomainException(OrderDomainException e) {
|
||||||
|
log.error("Error occurred: {}", e.getMessage());
|
||||||
|
return ErrorDTO.builder()
|
||||||
|
.code(HttpStatus.BAD_REQUEST.getReasonPhrase())
|
||||||
|
.message(e.getMessage())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@ResponseStatus(HttpStatus.NOT_FOUND)
|
||||||
|
@ExceptionHandler(value = {OrderNotFoundException.class})
|
||||||
|
@ResponseBody
|
||||||
|
public ErrorDTO handleOrderDomainException(OrderNotFoundException e) {
|
||||||
|
log.error("Error occurred: {}", e.getMessage());
|
||||||
|
return ErrorDTO.builder()
|
||||||
|
.code(HttpStatus.NOT_FOUND.getReasonPhrase())
|
||||||
|
.message(e.getMessage())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -19,6 +19,16 @@
|
|||||||
<groupId>com.food.order</groupId>
|
<groupId>com.food.order</groupId>
|
||||||
<artifactId>order-application-service</artifactId>
|
<artifactId>order-application-service</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.postgresql</groupId>
|
||||||
|
<artifactId>postgresql</artifactId>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package com.food.order.system.data.access.customer.adapter;
|
||||||
|
|
||||||
|
import com.food.order.domain.ports.output.repository.CustomerRepository;
|
||||||
|
import com.food.order.system.data.access.customer.mapper.CustomerDataAccessMapper;
|
||||||
|
import com.food.order.system.data.access.customer.repository.CustomerJPARepository;
|
||||||
|
import com.food.order.system.domain.entity.Customer;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class CustomerRepositoryImpl implements CustomerRepository {
|
||||||
|
|
||||||
|
|
||||||
|
private final CustomerJPARepository customerJpaRepository;
|
||||||
|
private final CustomerDataAccessMapper customerDataAccessMapper;
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<Customer> findCustomer(UUID customerId) {
|
||||||
|
return customerJpaRepository.findById(customerId)
|
||||||
|
.map(customerDataAccessMapper::customerEntityToCustomer);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package com.food.order.system.data.access.customer.entity;
|
||||||
|
|
||||||
|
import lombok.*;
|
||||||
|
import org.hibernate.annotations.DynamicUpdate;
|
||||||
|
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@DynamicUpdate
|
||||||
|
@Table(name = "order_customer_m_view",schema = "customer")
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@Builder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class CustomerEntity {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
private UUID id;
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package com.food.order.system.data.access.customer.mapper;
|
||||||
|
|
||||||
|
import com.food.order.domain.valueobject.CustomerId;
|
||||||
|
import com.food.order.system.data.access.customer.entity.CustomerEntity;
|
||||||
|
import com.food.order.system.domain.entity.Customer;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class CustomerDataAccessMapper {
|
||||||
|
|
||||||
|
public Customer customerEntityToCustomer(CustomerEntity customerEntity) {
|
||||||
|
return new Customer(new CustomerId(customerEntity.getId()));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package com.food.order.system.data.access.customer.repository;
|
||||||
|
|
||||||
|
import com.food.order.system.data.access.customer.entity.CustomerEntity;
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Repository
|
||||||
|
public interface CustomerJPARepository extends JpaRepository<CustomerEntity, UUID> {
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package com.food.order.system.data.access.order.adapter;
|
||||||
|
|
||||||
|
import com.food.order.domain.ports.output.repository.OrderRepository;
|
||||||
|
import com.food.order.system.data.access.order.mapper.OrderDataAccessMapper;
|
||||||
|
import com.food.order.system.data.access.order.repository.OrderJpaRepository;
|
||||||
|
import com.food.order.system.domain.entity.Order;
|
||||||
|
import com.food.order.system.domain.valueobject.TrackingId;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@Slf4j
|
||||||
|
public class OrderRepositoryImpl implements OrderRepository {
|
||||||
|
|
||||||
|
private final OrderJpaRepository orderJpaRepository;
|
||||||
|
private final OrderDataAccessMapper orderDataAccessMapper;
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Order save(Order order) {
|
||||||
|
return orderDataAccessMapper.orderEntityToOrder(orderJpaRepository
|
||||||
|
.save(orderDataAccessMapper.orderToOrderEntity(order)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<Order> findByTrackingId(TrackingId trackingId) {
|
||||||
|
return orderJpaRepository.findByTrackingId(trackingId.getValue())
|
||||||
|
.map(orderDataAccessMapper::orderEntityToOrder);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
package com.food.order.system.data.access.order.entity;
|
||||||
|
|
||||||
|
import lombok.*;
|
||||||
|
import org.hibernate.annotations.DynamicUpdate;
|
||||||
|
|
||||||
|
import javax.persistence.*;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@DynamicUpdate
|
||||||
|
@Table(name = "order_address")
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@Builder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class OrderAddressEntity {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
private UUID id;
|
||||||
|
|
||||||
|
@OneToOne(cascade = CascadeType.ALL)
|
||||||
|
@JoinColumn(name = "ORDER_ID")
|
||||||
|
private OrderEntity order;
|
||||||
|
|
||||||
|
private String street;
|
||||||
|
private String city;
|
||||||
|
private String postalCode;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (!(o instanceof OrderAddressEntity that)) return false;
|
||||||
|
return id.equals(that.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return id.hashCode();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
package com.food.order.system.data.access.order.entity;
|
||||||
|
|
||||||
|
import com.food.order.domain.valueobject.OrderStatus;
|
||||||
|
import lombok.*;
|
||||||
|
import org.hibernate.annotations.DynamicUpdate;
|
||||||
|
|
||||||
|
import javax.persistence.*;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@DynamicUpdate
|
||||||
|
@Table(name = "orders")
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@Builder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class OrderEntity {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
private UUID id;
|
||||||
|
|
||||||
|
private UUID customerId;
|
||||||
|
|
||||||
|
private UUID restaurantId;
|
||||||
|
|
||||||
|
private UUID trackingId;
|
||||||
|
|
||||||
|
@Enumerated(EnumType.STRING)
|
||||||
|
private OrderStatus orderStatus;
|
||||||
|
|
||||||
|
private BigDecimal price;
|
||||||
|
|
||||||
|
private String failureMessages;
|
||||||
|
|
||||||
|
@OneToOne(mappedBy = "order", cascade = CascadeType.ALL)
|
||||||
|
private OrderAddressEntity address;
|
||||||
|
|
||||||
|
@OneToMany(mappedBy = "orderEntity", cascade = CascadeType.ALL)
|
||||||
|
private List<OrderItemEntity> items;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (!(o instanceof OrderEntity that)) return false;
|
||||||
|
return id.equals(that.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return id.hashCode();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
package com.food.order.system.data.access.order.entity;
|
||||||
|
|
||||||
|
import lombok.*;
|
||||||
|
import org.hibernate.annotations.DynamicUpdate;
|
||||||
|
|
||||||
|
import javax.persistence.*;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@DynamicUpdate
|
||||||
|
@Table(name = "order_items")
|
||||||
|
@IdClass(OrderItemEntityId.class)
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@Builder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class OrderItemEntity {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
private Long id;
|
||||||
|
@Id
|
||||||
|
@ManyToOne(cascade = CascadeType.ALL)
|
||||||
|
@JoinColumn(name = "ORDER_ID")
|
||||||
|
private OrderEntity orderEntity;
|
||||||
|
|
||||||
|
private UUID productId;
|
||||||
|
|
||||||
|
private Integer quantity;
|
||||||
|
|
||||||
|
private BigDecimal price;
|
||||||
|
|
||||||
|
private BigDecimal subTotal;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (!(o instanceof OrderItemEntity that)) return false;
|
||||||
|
if (!id.equals(that.id)) return false;
|
||||||
|
return orderEntity.equals(that.orderEntity);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int result = id.hashCode();
|
||||||
|
result = 31 * result + orderEntity.hashCode();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package com.food.order.system.data.access.order.entity;
|
||||||
|
|
||||||
|
import lombok.*;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@Builder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class OrderItemEntityId implements Serializable {
|
||||||
|
|
||||||
|
private Long id;
|
||||||
|
private OrderEntity order;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (!(o instanceof OrderItemEntityId that)) return false;
|
||||||
|
return id.equals(that.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return id.hashCode();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,92 @@
|
|||||||
|
package com.food.order.system.data.access.order.mapper;
|
||||||
|
|
||||||
|
import com.food.order.domain.valueobject.*;
|
||||||
|
import com.food.order.system.data.access.order.entity.OrderAddressEntity;
|
||||||
|
import com.food.order.system.data.access.order.entity.OrderEntity;
|
||||||
|
import com.food.order.system.data.access.order.entity.OrderItemEntity;
|
||||||
|
import com.food.order.system.domain.entity.Order;
|
||||||
|
import com.food.order.system.domain.entity.OrderItem;
|
||||||
|
import com.food.order.system.domain.entity.Product;
|
||||||
|
import com.food.order.system.domain.valueobject.OrderItemId;
|
||||||
|
import com.food.order.system.domain.valueobject.StreetAddress;
|
||||||
|
import com.food.order.system.domain.valueobject.TrackingId;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static com.food.order.system.domain.entity.Order.FAILURE_MESSAGE_DELIMITER;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class OrderDataAccessMapper {
|
||||||
|
|
||||||
|
public OrderEntity orderToOrderEntity(Order order){
|
||||||
|
OrderEntity orderEntity = new OrderEntity();
|
||||||
|
orderEntity.setId(order.getId().getValue());
|
||||||
|
orderEntity.setOrderStatus(order.getStatus());
|
||||||
|
orderEntity.setCustomerId(order.getCustomerId().getValue());
|
||||||
|
orderEntity.setRestaurantId(order.getRestaurantId().getValue());
|
||||||
|
orderEntity.setTrackingId(order.getTrackingId().getValue());
|
||||||
|
orderEntity.setAddress(deliveryAddressToAddressEntity(order.getDeliveryAddress()));
|
||||||
|
orderEntity.setPrice(order.getPrice().getAmount());
|
||||||
|
orderEntity.setItems(orderItemsToOrderItemsEntity(order.getItems()));
|
||||||
|
orderEntity.setFailureMessages(order.getFailureMessages() != null ?
|
||||||
|
String.join(FAILURE_MESSAGE_DELIMITER, order.getFailureMessages()) : "");
|
||||||
|
orderEntity.getAddress().setOrder(orderEntity);
|
||||||
|
orderEntity.getItems().forEach(item -> item.setOrderEntity(orderEntity));
|
||||||
|
return orderEntity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Order orderEntityToOrder(OrderEntity orderEntity){
|
||||||
|
return Order.builder()
|
||||||
|
.orderId(new OrderId(orderEntity.getId()))
|
||||||
|
.customerId(new CustomerId(orderEntity.getCustomerId()))
|
||||||
|
.restaurantId(new RestaurantId(orderEntity.getRestaurantId()))
|
||||||
|
.deliveryAddress(addressEntityToDeliveryAddress(orderEntity.getAddress()))
|
||||||
|
.price(new Money(orderEntity.getPrice()))
|
||||||
|
.items(orderItemsEntityToOrderItems(orderEntity.getItems()))
|
||||||
|
.trackingId(new TrackingId(orderEntity.getTrackingId()))
|
||||||
|
.status(orderEntity.getOrderStatus())
|
||||||
|
.failureMessages(orderEntity.getFailureMessages() != null ?
|
||||||
|
List.of(orderEntity.getFailureMessages().split(FAILURE_MESSAGE_DELIMITER)) :
|
||||||
|
new ArrayList<>())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<OrderItem> orderItemsEntityToOrderItems(List<OrderItemEntity> items) {
|
||||||
|
return items.stream()
|
||||||
|
.map(item -> OrderItem.builder()
|
||||||
|
.orderItemId(new OrderItemId(item.getId()))
|
||||||
|
.product(new Product(new ProductId(item.getProductId())))
|
||||||
|
.quantity(item.getQuantity())
|
||||||
|
.price(new Money(item.getPrice()))
|
||||||
|
.subTotal(new Money(item.getSubTotal()))
|
||||||
|
.build())
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private StreetAddress addressEntityToDeliveryAddress(OrderAddressEntity address) {
|
||||||
|
return new StreetAddress(address.getId(),address.getStreet(), address.getCity() , address.getPostalCode());
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<OrderItemEntity> orderItemsToOrderItemsEntity(List<OrderItem> items) {
|
||||||
|
return items.stream()
|
||||||
|
.map(item -> OrderItemEntity.builder()
|
||||||
|
.id(item.getId().getValue())
|
||||||
|
.productId(item.getProduct().getId().getValue())
|
||||||
|
.price(item.getPrice().getAmount())
|
||||||
|
.quantity(item.getQuantity())
|
||||||
|
.subTotal(item.getSubTotal().getAmount())
|
||||||
|
.build())
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private OrderAddressEntity deliveryAddressToAddressEntity(StreetAddress deliveryAddress) {
|
||||||
|
OrderAddressEntity orderAddressEntity = new OrderAddressEntity();
|
||||||
|
orderAddressEntity.setId(deliveryAddress.getId());
|
||||||
|
orderAddressEntity.setStreet(deliveryAddress.getStreet());
|
||||||
|
orderAddressEntity.setCity(deliveryAddress.getCity());
|
||||||
|
orderAddressEntity.setPostalCode(deliveryAddress.getPostalCode());
|
||||||
|
return orderAddressEntity;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package com.food.order.system.data.access.order.repository;
|
||||||
|
|
||||||
|
import com.food.order.system.data.access.order.entity.OrderEntity;
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Repository
|
||||||
|
public interface OrderJpaRepository extends JpaRepository<OrderEntity, UUID> {
|
||||||
|
|
||||||
|
Optional<OrderEntity> findByTrackingId(UUID trackingId);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package com.food.order.system.data.access.restaurant.adapter;
|
||||||
|
|
||||||
|
import com.food.order.domain.ports.output.repository.RestaurantRepository;
|
||||||
|
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 lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class RestaurantRepositoryImpl implements RestaurantRepository {
|
||||||
|
|
||||||
|
private final RestaurantJpaRepository restaurantJpaRepository;
|
||||||
|
private final RestaurantDataAccessMapper restaurantDataAccessMapper;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<Restaurant> findRestaurantInformation(Restaurant restaurant) {
|
||||||
|
return restaurantJpaRepository.findByRestaurantIdAndProductIdIn
|
||||||
|
(restaurant.getId().getValue(),
|
||||||
|
restaurantDataAccessMapper.restaurantToRestaurantProducts(restaurant))
|
||||||
|
.map(restaurantDataAccessMapper::restaurantEntityToRestaurant);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
package com.food.order.system.data.access.restaurant.entity;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.*;
|
||||||
|
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.IdClass;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table(name = "order_restaurant_m_view",schema = "restaurant")
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@Builder
|
||||||
|
@IdClass(RestaurantEntityId.class)
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class RestaurantEntity {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
private UUID restaurantId;
|
||||||
|
|
||||||
|
@Id
|
||||||
|
private UUID productId;
|
||||||
|
|
||||||
|
private String restaurantName;
|
||||||
|
|
||||||
|
private Boolean restaurantActive;
|
||||||
|
|
||||||
|
private String productName;
|
||||||
|
|
||||||
|
private BigDecimal productPrice;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (!(o instanceof RestaurantEntity that)) return false;
|
||||||
|
if (!restaurantId.equals(that.restaurantId)) return false;
|
||||||
|
return productId.equals(that.productId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int result = restaurantId.hashCode();
|
||||||
|
result = 31 * result + productId.hashCode();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
package com.food.order.system.data.access.restaurant.entity;
|
||||||
|
|
||||||
|
import lombok.*;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@Builder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class RestaurantEntityId implements Serializable {
|
||||||
|
|
||||||
|
private UUID restaurantId;
|
||||||
|
private UUID productId;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (!(o instanceof RestaurantEntityId that)) return false;
|
||||||
|
if (!restaurantId.equals(that.restaurantId)) return false;
|
||||||
|
return productId.equals(that.productId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int result = restaurantId.hashCode();
|
||||||
|
result = 31 * result + productId.hashCode();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package com.food.order.system.data.access.restaurant.exception;
|
||||||
|
|
||||||
|
public class RestaurantDataAccessException extends RuntimeException{
|
||||||
|
public RestaurantDataAccessException(String s) {
|
||||||
|
super(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package com.food.order.system.data.access.restaurant.mapper;
|
||||||
|
|
||||||
|
import com.food.order.domain.valueobject.Money;
|
||||||
|
import com.food.order.domain.valueobject.ProductId;
|
||||||
|
import com.food.order.domain.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;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class RestaurantDataAccessMapper {
|
||||||
|
|
||||||
|
public List<UUID> restaurantToRestaurantProducts(Restaurant restaurant) {
|
||||||
|
return restaurant.getProducts()
|
||||||
|
.stream()
|
||||||
|
.map(product -> product.getId().getValue())
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Restaurant restaurantEntityToRestaurant(List<RestaurantEntity> restaurantEntities) {
|
||||||
|
var restaurantEntity =
|
||||||
|
restaurantEntities.stream().findFirst()
|
||||||
|
.orElseThrow(() -> new RestaurantDataAccessException("No restaurant found"));
|
||||||
|
var restaurantProducts = restaurantEntities.stream()
|
||||||
|
.map(entity -> new Product(new ProductId(entity.getProductId()),
|
||||||
|
entity.getProductName(),
|
||||||
|
new Money(entity.getProductPrice()))).toList();
|
||||||
|
return Restaurant.builder()
|
||||||
|
.id(new RestaurantId(restaurantEntity.getRestaurantId()))
|
||||||
|
.products(restaurantProducts)
|
||||||
|
.isActive(restaurantEntity.getRestaurantActive())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package com.food.order.system.data.access.restaurant.repository;
|
||||||
|
|
||||||
|
import com.food.order.system.data.access.restaurant.entity.RestaurantEntity;
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Repository
|
||||||
|
public interface RestaurantJpaRepository extends JpaRepository<RestaurantEntity, UUID> {
|
||||||
|
Optional<List<RestaurantEntity>> findByRestaurantIdAndProductIdIn(UUID restaurantId, List<UUID> productIds);
|
||||||
|
}
|
||||||
@@ -1,8 +1,6 @@
|
|||||||
package com.food.order.domain.dto.create;
|
package com.food.order.domain.dto.create;
|
||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.Getter;
|
|
||||||
|
|
||||||
import javax.validation.constraints.NotNull;
|
import javax.validation.constraints.NotNull;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package com.food.order.domain.dto.track;
|
package com.food.order.domain.dto.track;
|
||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
|
|
||||||
import javax.validation.constraints.NotNull;
|
import javax.validation.constraints.NotNull;
|
||||||
|
|||||||
@@ -4,4 +4,11 @@ import com.food.order.domain.entity.AggregateRoot;
|
|||||||
import com.food.order.domain.valueobject.CustomerId;
|
import com.food.order.domain.valueobject.CustomerId;
|
||||||
|
|
||||||
public class Customer extends AggregateRoot<CustomerId> {
|
public class Customer extends AggregateRoot<CustomerId> {
|
||||||
|
|
||||||
|
public Customer(){
|
||||||
|
|
||||||
|
}
|
||||||
|
public Customer (CustomerId id) {
|
||||||
|
super.setId(id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ import java.util.UUID;
|
|||||||
|
|
||||||
public class Order extends AggregateRoot<OrderId> {
|
public class Order extends AggregateRoot<OrderId> {
|
||||||
|
|
||||||
|
public static final String FAILURE_MESSAGE_DELIMITER = ",";
|
||||||
|
|
||||||
private final CustomerId customerId;
|
private final CustomerId customerId;
|
||||||
private final RestaurantId restaurantId;
|
private final RestaurantId restaurantId;
|
||||||
private final StreetAddress deliveryAddress;
|
private final StreetAddress deliveryAddress;
|
||||||
|
|||||||
5
pom.xml
5
pom.xml
@@ -58,6 +58,11 @@
|
|||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.food.order</groupId>
|
||||||
|
<artifactId>common-application</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.food.order</groupId>
|
<groupId>com.food.order</groupId>
|
||||||
|
|||||||
Reference in New Issue
Block a user