diff --git a/miranum-platform-showcase/README.md b/miranum-platform-showcase/README.md new file mode 100644 index 0000000..95be4f6 --- /dev/null +++ b/miranum-platform-showcase/README.md @@ -0,0 +1,38 @@ +# Miranum Platform Showcase + +## Architecture + +![arch](./images/miranum-platform-arch.png) + +## Process + +![process](./images/process.png) + +### Start process + +```json +{ + "customerName": "John Doe", + "customerAddress": "Main Street 1, London", + "items": { + "123": 2, + "456": 1 + } +} +``` + +```shell +curl --header "Content-Type: application/json" --request POST --data '{"customerName":"John Doe","customerAddress":"Main Street 1, London","items":{"123":2,"456":1}}' http://localhost:8081/api/place-order +``` + +### Get tasks + +```shell +curl -H "Accept: application/json" http://localhost:8081/api/task +``` + +### Complete task + +```shell +curl --header "Content-Type: application/json" --request POST --data 'true' http://localhost:8081/api/task/complete/960ce524-199a-11ef-b22f-0242ac150002 +``` diff --git a/miranum-platform-showcase/images/miranum-platform-arch.png b/miranum-platform-showcase/images/miranum-platform-arch.png new file mode 100644 index 0000000..f6eaec4 Binary files /dev/null and b/miranum-platform-showcase/images/miranum-platform-arch.png differ diff --git a/miranum-platform-showcase/images/process.png b/miranum-platform-showcase/images/process.png new file mode 100644 index 0000000..a494c62 Binary files /dev/null and b/miranum-platform-showcase/images/process.png differ diff --git a/miranum-platform-showcase/order-c7/pom.xml b/miranum-platform-showcase/order-c7/pom.xml new file mode 100644 index 0000000..f63fd41 --- /dev/null +++ b/miranum-platform-showcase/order-c7/pom.xml @@ -0,0 +1,69 @@ + + + 4.0.0 + + io.miragon.miranum.consulting + miranum-platform-showcase + 0.0.1-SNAPSHOT + + + order-c7 + + + + + org.springframework.boot + spring-boot-starter + + + org.springframework.boot + spring-boot-starter-web + + + + + org.camunda.community + camunda-engine-rest-client-complete-springboot-starter + ${camunda7.version} + + + + + io.miragon.miranum.connect + process-camunda7-remote + ${miranum.connect.version} + + + io.miragon.miranum.connect + worker-camunda7-remote + ${miranum.connect.version} + + + + io.miragon.miranum.consulting + order-core + ${project.version} + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + io.miragon.order.OrderApplication + + + + + repackage + + + + + + + diff --git a/miranum-platform-showcase/order-c7/src/main/java/io/miragon/order/OrderApplication.java b/miranum-platform-showcase/order-c7/src/main/java/io/miragon/order/OrderApplication.java new file mode 100644 index 0000000..a152d83 --- /dev/null +++ b/miranum-platform-showcase/order-c7/src/main/java/io/miragon/order/OrderApplication.java @@ -0,0 +1,13 @@ +package io.miragon.order; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class OrderApplication +{ + public static void main(String[] args) + { + SpringApplication.run(OrderApplication.class, args); + } +} diff --git a/miranum-platform-showcase/order-c7/src/main/java/io/miragon/order/adapter/TaskController.java b/miranum-platform-showcase/order-c7/src/main/java/io/miragon/order/adapter/TaskController.java new file mode 100644 index 0000000..9ef4465 --- /dev/null +++ b/miranum-platform-showcase/order-c7/src/main/java/io/miragon/order/adapter/TaskController.java @@ -0,0 +1,71 @@ +package io.miragon.order.adapter; + +import lombok.AllArgsConstructor; +import org.camunda.community.rest.client.api.ProcessInstanceApi; +import org.camunda.community.rest.client.api.TaskApi; +import org.camunda.community.rest.client.dto.CompleteTaskDto; +import org.camunda.community.rest.client.dto.TaskDto; +import org.camunda.community.rest.client.dto.TaskQueryDto; +import org.camunda.community.rest.client.dto.VariableValueDto; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +@RestController +@RequestMapping("/api/task") +@AllArgsConstructor +public class TaskController +{ + private final TaskApi taskApi; + + private final ProcessInstanceApi processInstanceApi; + + @GetMapping() + public ResponseEntity>> getTask() + { + TaskQueryDto taskQueryDto = new TaskQueryDto() + .taskDefinitionKey("Task_CheckOrderSales"); + + try { + List tasks = taskApi.queryTasks(0, 10, taskQueryDto); + Map> taskVariables = new HashMap<>(); + + for (TaskDto task : tasks) { + Map variables = + processInstanceApi.getProcessInstanceVariables(task.getProcessInstanceId(), false); + + Map variablesMap = variables + .entrySet() + .stream() + .map(entry -> Map.entry(entry.getKey(), entry.getValue().getValue())) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + + taskVariables.put(task.getId(), variablesMap); + } + + return new ResponseEntity<>(taskVariables, HttpStatus.OK); + } catch (Exception e) { + return new ResponseEntity<>(null, HttpStatus.BAD_REQUEST); + } + } + + @CrossOrigin + @PostMapping("/complete/{taskId}") + public ResponseEntity completeTask(@PathVariable String taskId, @RequestBody boolean isAccepted) + { + try { + CompleteTaskDto completeTaskDto = new CompleteTaskDto(); + completeTaskDto.setVariables(Map.of("isAccepted", new VariableValueDto().value(isAccepted))); + + taskApi.complete(taskId, completeTaskDto); + return new ResponseEntity<>(true, HttpStatus.OK); + } catch (Exception e) { + return new ResponseEntity<>(false, HttpStatus.BAD_REQUEST); + } + } +} diff --git a/miranum-platform-showcase/order-c7/src/main/resources/application.yml b/miranum-platform-showcase/order-c7/src/main/resources/application.yml new file mode 100644 index 0000000..eb38fea --- /dev/null +++ b/miranum-platform-showcase/order-c7/src/main/resources/application.yml @@ -0,0 +1,7 @@ +server: + port: 8081 + +camunda: + bpm: + client: + base-url: http://localhost:8080/engine-rest diff --git a/miranum-platform-showcase/order-c7/src/main/resources/order.bpmn b/miranum-platform-showcase/order-c7/src/main/resources/order.bpmn new file mode 100644 index 0000000..a19074a --- /dev/null +++ b/miranum-platform-showcase/order-c7/src/main/resources/order.bpmn @@ -0,0 +1,193 @@ + + + + + Flow_1vjtc84 + + + + Flow_1vjtc84 + Flow_1958sdy + Flow_0hl28eg + + + + + ${orderId} + ${isAccepted} + + + Flow_1958sdy + Flow_1a5l188 + + + ${orderValue < 10000} + + + + + ${orderId} + ${isAccepted} + + + Flow_0hl28eg + Flow_0sywpuj + + + ${orderValue >= 10000} + + + Flow_1a5l188 + Flow_0sywpuj + Flow_1jm1inj + + + + + + + + ${orderId} + + + Flow_1uvh5mc + Flow_1skq0xi + + + Flow_17l502p + + + + + + ${orderId} + + + Flow_1skq0xi + Flow_17l502p + + + + Flow_1jm1inj + Flow_1uvh5mc + Flow_0k5i5i9 + + + ${isAccepted == true} + + + Flow_0k5i5i9 + + + ${isAccepted == false} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/miranum-platform-showcase/order-core/pom.xml b/miranum-platform-showcase/order-core/pom.xml new file mode 100644 index 0000000..2a6e04e --- /dev/null +++ b/miranum-platform-showcase/order-core/pom.xml @@ -0,0 +1,40 @@ + + + 4.0.0 + + io.miragon.miranum.consulting + miranum-platform-showcase + 0.0.1-SNAPSHOT + + + order-core + + + + org.springframework.boot + spring-boot-starter + + + org.springframework.boot + spring-boot-starter-web + + + + io.miragon.miranum.connect + connect-process-api + ${miranum.connect.version} + + + io.miragon.miranum.connect + connect-worker-api + ${miranum.connect.version} + + + + com.fasterxml.jackson.core + jackson-databind + + + diff --git a/miranum-platform-showcase/order-core/src/main/java/io/miragon/order/adapter/in/process/MiranumAutoConfiguration.java b/miranum-platform-showcase/order-core/src/main/java/io/miragon/order/adapter/in/process/MiranumAutoConfiguration.java new file mode 100644 index 0000000..3cf8e99 --- /dev/null +++ b/miranum-platform-showcase/order-core/src/main/java/io/miragon/order/adapter/in/process/MiranumAutoConfiguration.java @@ -0,0 +1,19 @@ +package io.miragon.order.adapter.in.process; + +import io.miragon.order.application.port.in.DeliverOrderUseCase; +import io.miragon.order.application.port.in.PrepareDeliveryUseCase; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class MiranumAutoConfiguration +{ + @Bean + public MiranumWorkerAdapter miranumWorkerAdapter( + final PrepareDeliveryUseCase prepareDeliveryUseCase, + final DeliverOrderUseCase deliverOrderUseCase + ) + { + return new MiranumWorkerAdapter(prepareDeliveryUseCase, deliverOrderUseCase); + } +} diff --git a/miranum-platform-showcase/order-core/src/main/java/io/miragon/order/adapter/in/process/MiranumWorkerAdapter.java b/miranum-platform-showcase/order-core/src/main/java/io/miragon/order/adapter/in/process/MiranumWorkerAdapter.java new file mode 100644 index 0000000..f96f74c --- /dev/null +++ b/miranum-platform-showcase/order-core/src/main/java/io/miragon/order/adapter/in/process/MiranumWorkerAdapter.java @@ -0,0 +1,32 @@ +package io.miragon.order.adapter.in.process; + +import io.miragon.miranum.connect.worker.api.Worker; +import io.miragon.order.application.port.in.DeliverOrderUseCase; +import io.miragon.order.application.port.in.PrepareDeliveryUseCase; +import lombok.AllArgsConstructor; + +import java.util.Map; + +@AllArgsConstructor +public class MiranumWorkerAdapter +{ + private final PrepareDeliveryUseCase prepareDeliveryUseCase; + + private final DeliverOrderUseCase deliverOrderUseCase; + + @Worker(type = "prepareDelivery") + public void prepareDelivery(Map variables) + { + var orderId = (String) variables.get("orderId"); + PrepareDeliveryUseCase.PrepareDeliveryCommand command = new PrepareDeliveryUseCase.PrepareDeliveryCommand(orderId); + prepareDeliveryUseCase.prepareDelivery(command); + } + + @Worker(type = "deliverItems") + public void deliverItems(Map variables) + { + var orderId = (String) variables.get("orderId"); + DeliverOrderUseCase.DeliverItemsCommand command = new DeliverOrderUseCase.DeliverItemsCommand(orderId); + deliverOrderUseCase.deliverItems(command); + } +} diff --git a/miranum-platform-showcase/order-core/src/main/java/io/miragon/order/adapter/in/rest/CheckOrderController.java b/miranum-platform-showcase/order-core/src/main/java/io/miragon/order/adapter/in/rest/CheckOrderController.java new file mode 100644 index 0000000..64f569e --- /dev/null +++ b/miranum-platform-showcase/order-core/src/main/java/io/miragon/order/adapter/in/rest/CheckOrderController.java @@ -0,0 +1,43 @@ +package io.miragon.order.adapter.in.rest; + +import io.miragon.order.application.port.in.GetOrderUseCase; +import lombok.AllArgsConstructor; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequestMapping("/api/order") +@AllArgsConstructor +public class CheckOrderController +{ + private final GetOrderUseCase getOrderUseCase; + + @GetMapping("/{orderId}") + public ResponseEntity checkOrder(@PathVariable String orderId) + { + var order = getOrderUseCase.getOrder(new GetOrderUseCase.GetOrderQuery(orderId)); + if (order == null) { + return new ResponseEntity<>(null, HttpStatus.BAD_REQUEST); + } + + OrderDto response = new OrderDto( + order.getItems(), + order.getStatus().toString(), + order.getCustomerName(), + order.getCustomerAddress() + ); + return new ResponseEntity<>(response, HttpStatus.CREATED); + } + + @CrossOrigin + @PostMapping("/check/{orderId}") + public ResponseEntity completeCheck(@PathVariable String orderId, @RequestBody boolean isAccepted) + { + if (isAccepted) { + return new ResponseEntity<>(true, HttpStatus.OK); + } else { + return new ResponseEntity<>(false, HttpStatus.BAD_REQUEST); + } + } +} diff --git a/miranum-platform-showcase/order-core/src/main/java/io/miragon/order/adapter/in/rest/OrderDto.java b/miranum-platform-showcase/order-core/src/main/java/io/miragon/order/adapter/in/rest/OrderDto.java new file mode 100644 index 0000000..6a26466 --- /dev/null +++ b/miranum-platform-showcase/order-core/src/main/java/io/miragon/order/adapter/in/rest/OrderDto.java @@ -0,0 +1,18 @@ +package io.miragon.order.adapter.in.rest; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.Map; + +@AllArgsConstructor +@NoArgsConstructor +@Getter +public class OrderDto +{ + Map items; + String status = "NEW"; + private String customerName; + private String customerAddress; +} diff --git a/miranum-platform-showcase/order-core/src/main/java/io/miragon/order/adapter/in/rest/PlaceOrderController.java b/miranum-platform-showcase/order-core/src/main/java/io/miragon/order/adapter/in/rest/PlaceOrderController.java new file mode 100644 index 0000000..43f2295 --- /dev/null +++ b/miranum-platform-showcase/order-core/src/main/java/io/miragon/order/adapter/in/rest/PlaceOrderController.java @@ -0,0 +1,36 @@ +package io.miragon.order.adapter.in.rest; + +import io.miragon.order.application.port.in.PlaceOrderUseCase; +import lombok.AllArgsConstructor; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.UUID; + + +@RestController +@RequestMapping("/api/place-order") +@AllArgsConstructor +public class PlaceOrderController +{ + private final PlaceOrderUseCase placeOrderUseCase; + + @CrossOrigin + @PostMapping + public ResponseEntity placeOrder(@RequestBody OrderDto orderDto) + { + PlaceOrderUseCase.PlaceOrderCommand command = new PlaceOrderUseCase.PlaceOrderCommand( + orderDto.getCustomerName(), + orderDto.getCustomerAddress(), + orderDto.getItems() + ); + + try { + var orderId = placeOrderUseCase.placeOrder(command); + return new ResponseEntity<>(orderId, HttpStatus.CREATED); + } catch (Exception e) { + return new ResponseEntity<>(null, HttpStatus.BAD_REQUEST); + } + } +} diff --git a/miranum-platform-showcase/order-core/src/main/java/io/miragon/order/adapter/out/process/CompleteOrderCheck.java b/miranum-platform-showcase/order-core/src/main/java/io/miragon/order/adapter/out/process/CompleteOrderCheck.java new file mode 100644 index 0000000..c062018 --- /dev/null +++ b/miranum-platform-showcase/order-core/src/main/java/io/miragon/order/adapter/out/process/CompleteOrderCheck.java @@ -0,0 +1,17 @@ +package io.miragon.order.adapter.out.process; + +import io.miragon.order.application.port.out.CompleteOrderCheckPort; + +public class CompleteOrderCheck implements CompleteOrderCheckPort +{ + @Override + public boolean completeCheck(String processInstanceId) + { + // TODO: get task id + // * /task + // * processInstanceId + // * taskDefinitionKey + + return false; + } +} diff --git a/miranum-platform-showcase/order-core/src/main/java/io/miragon/order/adapter/out/process/StartProcessAdapter.java b/miranum-platform-showcase/order-core/src/main/java/io/miragon/order/adapter/out/process/StartProcessAdapter.java new file mode 100644 index 0000000..7a9a418 --- /dev/null +++ b/miranum-platform-showcase/order-core/src/main/java/io/miragon/order/adapter/out/process/StartProcessAdapter.java @@ -0,0 +1,25 @@ +package io.miragon.order.adapter.out.process; + +import io.miragon.miranum.connect.process.api.ProcessApi; +import io.miragon.miranum.connect.process.api.StartProcessCommand; +import io.miragon.order.application.port.out.StartProcessPort; +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Component; + +import java.util.Map; + +@Component +@AllArgsConstructor +public class StartProcessAdapter implements StartProcessPort +{ + private final ProcessApi processApi; + + @Override + public void startProcess(String orderId, double orderValue) + { + String processKey = "OrderProcess"; + Map variables = Map.of("orderId", orderId, "orderValue", orderValue); + var startProcessCommand = new StartProcessCommand(processKey, variables); + processApi.startProcess(startProcessCommand); + } +} diff --git a/miranum-platform-showcase/order-core/src/main/java/io/miragon/order/adapter/out/repository/ItemEntity.java b/miranum-platform-showcase/order-core/src/main/java/io/miragon/order/adapter/out/repository/ItemEntity.java new file mode 100644 index 0000000..e1748cb --- /dev/null +++ b/miranum-platform-showcase/order-core/src/main/java/io/miragon/order/adapter/out/repository/ItemEntity.java @@ -0,0 +1,17 @@ +package io.miragon.order.adapter.out.repository; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@AllArgsConstructor +@Getter +public class ItemEntity +{ + String id; + + String name; + + String description; + + double price; +} diff --git a/miranum-platform-showcase/order-core/src/main/java/io/miragon/order/adapter/out/repository/ItemRepository.java b/miranum-platform-showcase/order-core/src/main/java/io/miragon/order/adapter/out/repository/ItemRepository.java new file mode 100644 index 0000000..97e7c56 --- /dev/null +++ b/miranum-platform-showcase/order-core/src/main/java/io/miragon/order/adapter/out/repository/ItemRepository.java @@ -0,0 +1,34 @@ +package io.miragon.order.adapter.out.repository; + +import io.miragon.order.application.port.out.ItemRepositoryPort; +import io.miragon.order.domain.Item; +import org.springframework.stereotype.Component; + +import java.util.List; + +@Component +public class ItemRepository implements ItemRepositoryPort +{ + private final List items = List.of( + new ItemEntity("123", "Item 1", "Item 1", 10.0), + new ItemEntity("456", "Item 2", "Item 2", 20.0), + new ItemEntity("789", "Item 3", "Item 3", 30.0) + ); + + @Override + public List readAllItems() + { + return items.stream() + .map(itemEntity -> new Item(itemEntity.getId(), itemEntity.getName(), itemEntity.getDescription(), itemEntity.getPrice())) + .toList(); + } + + @Override + public List readItemsById(String... ids) + { + return items.stream() + .filter(itemEntity -> List.of(ids).contains(itemEntity.getId())) + .map(itemEntity -> new Item(itemEntity.getId(), itemEntity.getName(), itemEntity.getDescription(), itemEntity.getPrice())) + .toList(); + } +} diff --git a/miranum-platform-showcase/order-core/src/main/java/io/miragon/order/adapter/out/repository/OrderEntity.java b/miranum-platform-showcase/order-core/src/main/java/io/miragon/order/adapter/out/repository/OrderEntity.java new file mode 100644 index 0000000..f689a39 --- /dev/null +++ b/miranum-platform-showcase/order-core/src/main/java/io/miragon/order/adapter/out/repository/OrderEntity.java @@ -0,0 +1,24 @@ +package io.miragon.order.adapter.out.repository; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Map; +import java.util.UUID; + +@AllArgsConstructor +@Getter +public class OrderEntity +{ + UUID id; + + String processInstanceId; + + String customerName; + + String customerAddress; + + Map items; + + String status; +} diff --git a/miranum-platform-showcase/order-core/src/main/java/io/miragon/order/adapter/out/repository/OrderRepository.java b/miranum-platform-showcase/order-core/src/main/java/io/miragon/order/adapter/out/repository/OrderRepository.java new file mode 100644 index 0000000..beef542 --- /dev/null +++ b/miranum-platform-showcase/order-core/src/main/java/io/miragon/order/adapter/out/repository/OrderRepository.java @@ -0,0 +1,92 @@ +package io.miragon.order.adapter.out.repository; + +import io.miragon.order.application.port.out.OrderRepositoryPort; +import io.miragon.order.domain.Order; +import org.springframework.stereotype.Component; + +import java.util.*; + +@Component +public class OrderRepository implements OrderRepositoryPort +{ + private final List orders = new ArrayList<>(); + + @Override + public UUID createOrder(Order order) + { + UUID id = UUID.randomUUID(); + OrderEntity orderEntity = new OrderEntity( + id, + "", + order.getCustomerName(), + order.getCustomerAddress(), + order.getItems(), + Order.OrderStatus.NEW.toString() + ); + orders.add(orderEntity); + return id; + } + + @Override + public Order readOrderById(UUID id) throws NoSuchElementException + { + var order = orders.stream().filter(o -> o.getId().equals(id)).findFirst(); + return order.map(orderEntity -> new Order( + orderEntity.getCustomerName(), + orderEntity.getCustomerAddress(), + orderEntity.getItems(), + Order.OrderStatus.valueOf(orderEntity.getStatus()) + )).orElseThrow(); + } + + @Override + public Map readOrderByCustomerName(String customerName) + { + List orderEntities = orders + .stream() + .filter(o -> o.getCustomerName().equals(customerName)) + .toList(); + + return orderEntities.stream().collect( + Map::of, + (map, orderEntity) -> map.put(orderEntity.getId(), new Order( + orderEntity.getCustomerName(), + orderEntity.getCustomerAddress(), + orderEntity.getItems(), + Order.OrderStatus.valueOf(orderEntity.getStatus()) + )), + Map::putAll + ); + } + + @Override + public boolean updateOrder(UUID id, Order order) + { + orders.removeIf(o -> o.getId().equals(id)); + orders.add(new OrderEntity( + id, + "", + order.getCustomerName(), + order.getCustomerAddress(), + order.getItems(), + order.getStatus().toString() + )); + return true; + } + + @Override + public Order deleteOrder(UUID id) throws IllegalArgumentException + { + var order = orders.stream().filter(o -> o.getId().equals(id)).findFirst(); + if (order.isPresent()) { + orders.remove(order.get()); + return new Order( + order.get().getCustomerName(), + order.get().getCustomerAddress(), + order.get().getItems(), + Order.OrderStatus.valueOf(order.get().getStatus()) + ); + } + throw new IllegalArgumentException("Order not found"); + } +} diff --git a/miranum-platform-showcase/order-core/src/main/java/io/miragon/order/application/port/in/DeliverOrderUseCase.java b/miranum-platform-showcase/order-core/src/main/java/io/miragon/order/application/port/in/DeliverOrderUseCase.java new file mode 100644 index 0000000..cb0a4b4 --- /dev/null +++ b/miranum-platform-showcase/order-core/src/main/java/io/miragon/order/application/port/in/DeliverOrderUseCase.java @@ -0,0 +1,21 @@ +package io.miragon.order.application.port.in; + +import lombok.Getter; + +import java.util.UUID; + +public interface DeliverOrderUseCase +{ + void deliverItems(DeliverItemsCommand command); + + @Getter + class DeliverItemsCommand + { + private final UUID orderId; + + public DeliverItemsCommand(String orderId) + { + this.orderId = UUID.fromString(orderId); + } + } +} diff --git a/miranum-platform-showcase/order-core/src/main/java/io/miragon/order/application/port/in/GetOrderUseCase.java b/miranum-platform-showcase/order-core/src/main/java/io/miragon/order/application/port/in/GetOrderUseCase.java new file mode 100644 index 0000000..84388c7 --- /dev/null +++ b/miranum-platform-showcase/order-core/src/main/java/io/miragon/order/application/port/in/GetOrderUseCase.java @@ -0,0 +1,22 @@ +package io.miragon.order.application.port.in; + +import io.miragon.order.domain.Order; +import lombok.Getter; + +import java.util.UUID; + +public interface GetOrderUseCase +{ + Order getOrder(GetOrderQuery query); + + @Getter + class GetOrderQuery + { + private final UUID orderId; + + public GetOrderQuery(String orderId) + { + this.orderId = UUID.fromString(orderId); + } + } +} diff --git a/miranum-platform-showcase/order-core/src/main/java/io/miragon/order/application/port/in/PlaceOrderUseCase.java b/miranum-platform-showcase/order-core/src/main/java/io/miragon/order/application/port/in/PlaceOrderUseCase.java new file mode 100644 index 0000000..7298608 --- /dev/null +++ b/miranum-platform-showcase/order-core/src/main/java/io/miragon/order/application/port/in/PlaceOrderUseCase.java @@ -0,0 +1,28 @@ +package io.miragon.order.application.port.in; + +import lombok.Getter; + +import java.util.Map; +import java.util.UUID; + +public interface PlaceOrderUseCase +{ + UUID placeOrder(PlaceOrderCommand placeOrderCommand); + + @Getter + class PlaceOrderCommand + { + private final String customerName; + + private final String customerAddress; + + private final Map items; + + public PlaceOrderCommand(String customerName, String customerAddress, Map items) + { + this.customerName = customerName; + this.customerAddress = customerAddress; + this.items = items; + } + } +} diff --git a/miranum-platform-showcase/order-core/src/main/java/io/miragon/order/application/port/in/PrepareDeliveryUseCase.java b/miranum-platform-showcase/order-core/src/main/java/io/miragon/order/application/port/in/PrepareDeliveryUseCase.java new file mode 100644 index 0000000..ba600d1 --- /dev/null +++ b/miranum-platform-showcase/order-core/src/main/java/io/miragon/order/application/port/in/PrepareDeliveryUseCase.java @@ -0,0 +1,20 @@ +package io.miragon.order.application.port.in; + +import lombok.Getter; + +import java.util.UUID; + +public interface PrepareDeliveryUseCase +{ + void prepareDelivery(PrepareDeliveryCommand command); + + @Getter + class PrepareDeliveryCommand + { + private final UUID orderId; + + public PrepareDeliveryCommand(String orderId) { + this.orderId = UUID.fromString(orderId); + } + } +} diff --git a/miranum-platform-showcase/order-core/src/main/java/io/miragon/order/application/port/out/CompleteOrderCheckPort.java b/miranum-platform-showcase/order-core/src/main/java/io/miragon/order/application/port/out/CompleteOrderCheckPort.java new file mode 100644 index 0000000..6a1e25e --- /dev/null +++ b/miranum-platform-showcase/order-core/src/main/java/io/miragon/order/application/port/out/CompleteOrderCheckPort.java @@ -0,0 +1,6 @@ +package io.miragon.order.application.port.out; + +public interface CompleteOrderCheckPort +{ + boolean completeCheck(String processInstanceId); +} diff --git a/miranum-platform-showcase/order-core/src/main/java/io/miragon/order/application/port/out/ItemRepositoryPort.java b/miranum-platform-showcase/order-core/src/main/java/io/miragon/order/application/port/out/ItemRepositoryPort.java new file mode 100644 index 0000000..b0f0625 --- /dev/null +++ b/miranum-platform-showcase/order-core/src/main/java/io/miragon/order/application/port/out/ItemRepositoryPort.java @@ -0,0 +1,12 @@ +package io.miragon.order.application.port.out; + +import io.miragon.order.domain.Item; + +import java.util.List; + +public interface ItemRepositoryPort +{ + List readAllItems(); + + List readItemsById(String... ids); +} diff --git a/miranum-platform-showcase/order-core/src/main/java/io/miragon/order/application/port/out/OrderRepositoryPort.java b/miranum-platform-showcase/order-core/src/main/java/io/miragon/order/application/port/out/OrderRepositoryPort.java new file mode 100644 index 0000000..6c7da2c --- /dev/null +++ b/miranum-platform-showcase/order-core/src/main/java/io/miragon/order/application/port/out/OrderRepositoryPort.java @@ -0,0 +1,19 @@ +package io.miragon.order.application.port.out; + +import io.miragon.order.domain.Order; + +import java.util.Map; +import java.util.UUID; + +public interface OrderRepositoryPort +{ + UUID createOrder(Order order); + + Order readOrderById(UUID id); + + Map readOrderByCustomerName(String customerName); + + boolean updateOrder(UUID id, Order order); + + Order deleteOrder(UUID id); +} diff --git a/miranum-platform-showcase/order-core/src/main/java/io/miragon/order/application/port/out/StartProcessPort.java b/miranum-platform-showcase/order-core/src/main/java/io/miragon/order/application/port/out/StartProcessPort.java new file mode 100644 index 0000000..09897ff --- /dev/null +++ b/miranum-platform-showcase/order-core/src/main/java/io/miragon/order/application/port/out/StartProcessPort.java @@ -0,0 +1,6 @@ +package io.miragon.order.application.port.out; + +public interface StartProcessPort +{ + void startProcess(String orderId, double orderValue); +} diff --git a/miranum-platform-showcase/order-core/src/main/java/io/miragon/order/application/service/DeliverOrderService.java b/miranum-platform-showcase/order-core/src/main/java/io/miragon/order/application/service/DeliverOrderService.java new file mode 100644 index 0000000..47a6805 --- /dev/null +++ b/miranum-platform-showcase/order-core/src/main/java/io/miragon/order/application/service/DeliverOrderService.java @@ -0,0 +1,27 @@ +package io.miragon.order.application.service; + +import io.miragon.order.application.port.in.DeliverOrderUseCase; +import io.miragon.order.application.port.out.OrderRepositoryPort; +import io.miragon.order.domain.Order; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +@Component +@AllArgsConstructor +@Slf4j +public class DeliverOrderService implements DeliverOrderUseCase +{ + private final OrderRepositoryPort orderRepositoryPort; + + @Override + public void deliverItems(DeliverItemsCommand command) + { + var orderId = command.getOrderId(); + Order order = orderRepositoryPort.readOrderById(orderId); + order.setStatus(Order.OrderStatus.DELIVERED); + orderRepositoryPort.updateOrder(orderId, order); + + log.info("Order {} with items {} has been delivered", orderId, order.getItems()); + } +} diff --git a/miranum-platform-showcase/order-core/src/main/java/io/miragon/order/application/service/GetOrderService.java b/miranum-platform-showcase/order-core/src/main/java/io/miragon/order/application/service/GetOrderService.java new file mode 100644 index 0000000..ae29280 --- /dev/null +++ b/miranum-platform-showcase/order-core/src/main/java/io/miragon/order/application/service/GetOrderService.java @@ -0,0 +1,20 @@ +package io.miragon.order.application.service; + +import io.miragon.order.application.port.in.GetOrderUseCase; +import io.miragon.order.application.port.out.OrderRepositoryPort; +import io.miragon.order.domain.Order; +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Component; + +@Component +@AllArgsConstructor +public class GetOrderService implements GetOrderUseCase +{ + private final OrderRepositoryPort orderRepositoryPort; + + @Override + public Order getOrder(GetOrderQuery query) + { + return orderRepositoryPort.readOrderById(query.getOrderId()); + } +} diff --git a/miranum-platform-showcase/order-core/src/main/java/io/miragon/order/application/service/PlaceOrderService.java b/miranum-platform-showcase/order-core/src/main/java/io/miragon/order/application/service/PlaceOrderService.java new file mode 100644 index 0000000..ae661c5 --- /dev/null +++ b/miranum-platform-showcase/order-core/src/main/java/io/miragon/order/application/service/PlaceOrderService.java @@ -0,0 +1,54 @@ +package io.miragon.order.application.service; + +import io.miragon.order.application.port.in.PlaceOrderUseCase; +import io.miragon.order.application.port.out.ItemRepositoryPort; +import io.miragon.order.application.port.out.OrderRepositoryPort; +import io.miragon.order.application.port.out.StartProcessPort; +import io.miragon.order.domain.Item; +import io.miragon.order.domain.Order; +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.UUID; + +@Component +@AllArgsConstructor +public class PlaceOrderService implements PlaceOrderUseCase +{ + private final StartProcessPort startProcessPort; + + private final ItemRepositoryPort itemRepositoryPort; + + private final OrderRepositoryPort orderRepositoryPort; + + @Override + public UUID placeOrder(PlaceOrderCommand placeOrderCommand) throws IllegalArgumentException + { + Order order = new Order( + placeOrderCommand.getCustomerName(), + placeOrderCommand.getCustomerAddress(), + placeOrderCommand.getItems(), + Order.OrderStatus.NEW + ); + + // Check if the ordered items exist + String[] itemIds = order.getItems().keySet().toArray(new String[0]); + List items = itemRepositoryPort.readItemsById(itemIds); + if (items.size() != itemIds.length) { + throw new IllegalArgumentException("Invalid item ids"); + } + + // Save order to a database + UUID orderId = orderRepositoryPort.createOrder(order); + + // Start process instance with order value + double orderValue = items.stream() + .mapToDouble(item -> item.getPrice() * order.getItems().get(item.getId())) + .sum(); + + startProcessPort.startProcess(orderId.toString(), orderValue); + + return orderId; + } +} diff --git a/miranum-platform-showcase/order-core/src/main/java/io/miragon/order/application/service/PrepareDeliveryService.java b/miranum-platform-showcase/order-core/src/main/java/io/miragon/order/application/service/PrepareDeliveryService.java new file mode 100644 index 0000000..78db80e --- /dev/null +++ b/miranum-platform-showcase/order-core/src/main/java/io/miragon/order/application/service/PrepareDeliveryService.java @@ -0,0 +1,27 @@ +package io.miragon.order.application.service; + +import io.miragon.order.application.port.in.PrepareDeliveryUseCase; +import io.miragon.order.application.port.out.OrderRepositoryPort; +import io.miragon.order.domain.Order; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +@Component +@AllArgsConstructor +@Slf4j +public class PrepareDeliveryService implements PrepareDeliveryUseCase +{ + private final OrderRepositoryPort orderRepositoryPort; + + @Override + public void prepareDelivery(PrepareDeliveryCommand command) + { + var orderId = command.getOrderId(); + Order order = orderRepositoryPort.readOrderById(orderId); + order.setStatus(Order.OrderStatus.IN_PROGRESS); + orderRepositoryPort.updateOrder(orderId, order); + + log.info("Order {} with items {} is being prepared for delivery", orderId, order.getItems()); + } +} diff --git a/miranum-platform-showcase/order-core/src/main/java/io/miragon/order/domain/Item.java b/miranum-platform-showcase/order-core/src/main/java/io/miragon/order/domain/Item.java new file mode 100644 index 0000000..bbe5f0a --- /dev/null +++ b/miranum-platform-showcase/order-core/src/main/java/io/miragon/order/domain/Item.java @@ -0,0 +1,17 @@ +package io.miragon.order.domain; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@AllArgsConstructor +@Getter +public class Item +{ + String id; + + String name; + + String description; + + double price; +} diff --git a/miranum-platform-showcase/order-core/src/main/java/io/miragon/order/domain/Order.java b/miranum-platform-showcase/order-core/src/main/java/io/miragon/order/domain/Order.java new file mode 100644 index 0000000..a971ce9 --- /dev/null +++ b/miranum-platform-showcase/order-core/src/main/java/io/miragon/order/domain/Order.java @@ -0,0 +1,29 @@ +package io.miragon.order.domain; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; + +import java.util.Map; + +@AllArgsConstructor +@Getter +@Setter +public class Order +{ + String customerName; + + String customerAddress; + + Map items; + + OrderStatus status; + + public enum OrderStatus + { + NEW, + IN_PROGRESS, + DELIVERED, + CANCELLED + } +} diff --git a/miranum-platform-showcase/pom.xml b/miranum-platform-showcase/pom.xml new file mode 100644 index 0000000..fa48bc1 --- /dev/null +++ b/miranum-platform-showcase/pom.xml @@ -0,0 +1,105 @@ + + + 4.0.0 + + io.miragon.miranum.consulting + miranum-platform-showcase + 0.0.1-SNAPSHOT + Miranum Platform Showcase + This project serves as a showcase for demonstrating Miranum Platform and Miranum Connect. + pom + + + 17 + 17 + 17 + UTF-8 + 0.3.2 + 0.6.0 + 3.1.5 + 1.18.32 + 7.20.0 + 3.2.5 + + + + order-c7 + order-core + + + + + + org.springframework.boot + spring-boot-dependencies + ${spring.boot.version} + pom + import + + + + + + + org.projectlombok + lombok + ${lombok.version} + provided + + + + + + + + org.apache.maven.plugins + maven-clean-plugin + 3.3.2 + + + org.apache.maven.plugins + maven-jar-plugin + 3.4.1 + + + org.apache.maven.plugins + maven-resources-plugin + 3.3.1 + + UTF-8 + + + + org.apache.maven.plugins + maven-install-plugin + 3.1.1 + + + org.apache.maven.plugins + maven-enforcer-plugin + 3.4.1 + + + enforce-maven + + enforce + + + + + 17 + + + 3.6.0 + + + + + + + + + + diff --git a/miranum-platform-showcase/stack/docker-compose.yml b/miranum-platform-showcase/stack/docker-compose.yml new file mode 100644 index 0000000..ed6d9a0 --- /dev/null +++ b/miranum-platform-showcase/stack/docker-compose.yml @@ -0,0 +1,7 @@ +# Use this only in dev environments. It's not intended for production usage. +version: '3.9' +services: + camunda: + image: camunda/camunda-bpm-platform:7.21.0 + ports: + - "8080:8080" diff --git a/pom.xml b/pom.xml index 6812ba3..544e3a3 100644 --- a/pom.xml +++ b/pom.xml @@ -16,6 +16,7 @@ process-example schema-client-example customer-onboarding-showcase + miranum-platform-showcase miranum-stack-showcase futue-proof-connector futue-proof-connector/notify-customer-connector