diff --git a/src/main/java/com/podzilla/order/controller/OrderController.java b/src/main/java/com/podzilla/order/controller/OrderController.java index acf7576..5cc5252 100644 --- a/src/main/java/com/podzilla/order/controller/OrderController.java +++ b/src/main/java/com/podzilla/order/controller/OrderController.java @@ -1,11 +1,6 @@ package com.podzilla.order.controller; import com.podzilla.mq.EventPublisher; -import com.podzilla.mq.EventsConstants; -import com.podzilla.mq.events.CartCheckedoutEvent; -import com.podzilla.mq.events.ConfirmationType; -import com.podzilla.mq.events.DeliveryAddress; -import com.podzilla.mq.events.OrderItem; import com.podzilla.order.model.Order; import com.podzilla.order.model.OrderLocation; import com.podzilla.order.model.OrderStatus; @@ -26,10 +21,6 @@ import io.swagger.v3.oas.annotations.responses.ApiResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - - -import java.math.BigDecimal; -import java.util.ArrayList; import java.util.List; import java.util.Optional; import java.util.UUID; @@ -89,34 +80,6 @@ public ResponseEntity getOrderById(@PathVariable final UUID id) { } - @GetMapping("/testEventPublisher") - public ResponseEntity testEventPublisher() { - LOGGER.info("Testing Event Publisher"); - List orderItems = new ArrayList<>(); - orderItems.add(new OrderItem(UUID.randomUUID().toString(), 5, new BigDecimal(100.0))); - DeliveryAddress deliveryAddress = new DeliveryAddress( - "123 Main St", - "Springfield", - "IL", - "USA", - "62701" - ); - CartCheckedoutEvent event = new CartCheckedoutEvent( - UUID.randomUUID().toString(), - UUID.randomUUID().toString(), - orderItems, - new BigDecimal(500.0), - deliveryAddress, - 10.0, - 20.0, - "signature", - ConfirmationType.SIGNATURE - ); - eventPublisher.publishEvent(EventsConstants.CART_CHECKEDOUT, event); - return ResponseEntity.ok("Event published successfully"); - } - - @PatchMapping("/{id}") @Operation(summary = "Update an order", description = "Updates an existing order and returns the updated " diff --git a/src/main/java/com/podzilla/order/controller/OrderPublisherController.java b/src/main/java/com/podzilla/order/controller/OrderPublisherController.java new file mode 100644 index 0000000..1e9e31a --- /dev/null +++ b/src/main/java/com/podzilla/order/controller/OrderPublisherController.java @@ -0,0 +1,150 @@ +//package com.podzilla.order.controller; +// +//import com.podzilla.mq.EventPublisher; +//import com.podzilla.mq.EventsConstants; +//import com.podzilla.mq.events.*; +//import com.podzilla.order.model.Order; +//import com.podzilla.order.model.OrderLocation; +//import com.podzilla.order.model.OrderStatus; +//import com.podzilla.order.service.OrderService; +//import io.swagger.v3.oas.annotations.tags.Tag; +//import org.springframework.beans.factory.annotation.Autowired; +//import org.springframework.http.ResponseEntity; +//import org.springframework.web.bind.annotation.DeleteMapping; +//import org.springframework.web.bind.annotation.GetMapping; +//import org.springframework.web.bind.annotation.PathVariable; +//import org.springframework.web.bind.annotation.PostMapping; +//import org.springframework.web.bind.annotation.PutMapping; +//import org.springframework.web.bind.annotation.RequestBody; +//import org.springframework.web.bind.annotation.RequestMapping; +//import org.springframework.web.bind.annotation.PatchMapping; +//import org.springframework.web.bind.annotation.RestController; +//import io.swagger.v3.oas.annotations.Operation; +//import io.swagger.v3.oas.annotations.responses.ApiResponse; +//import org.slf4j.Logger; +//import org.slf4j.LoggerFactory; +// +// +//import java.math.BigDecimal; +//import java.util.ArrayList; +//import java.util.List; +//import java.util.Optional; +//import java.util.UUID; +// +//@RestController +//@RequestMapping("/testOrders") +//@Tag(name = "Order API", description = "Order management operations") +//public class OrderPublisherController { +// private final OrderService orderService; +// private final EventPublisher eventPublisher; +// private static final Logger LOGGER = +// LoggerFactory.getLogger(OrderController.class); +// +// @Autowired +// public OrderPublisherController(final OrderService orderService, final EventPublisher eventPublisher) { +// this.orderService = orderService; +// this.eventPublisher = eventPublisher; +// } +// +// @GetMapping("/testPublishCartCheckoutEvent") +// public ResponseEntity testPublishCartCheckoutEvent() { +// LOGGER.info("Testing Event Publisher"); +// List orderItems = new ArrayList<>(); +// orderItems.add(new OrderItem(UUID.randomUUID().toString(), 5, new BigDecimal(100.0))); +// DeliveryAddress deliveryAddress = new DeliveryAddress( +// "123 Main St", +// "Springfield", +// "IL", +// "USA", +// "62701" +// ); +// CartCheckedoutEvent event = new CartCheckedoutEvent( +// UUID.randomUUID().toString(), +// UUID.randomUUID().toString(), +// orderItems, +// new BigDecimal(500.0), +// deliveryAddress, +// 10.0, +// 20.0, +// "signature", +// ConfirmationType.SIGNATURE +// ); +// eventPublisher.publishEvent(EventsConstants.CART_CHECKEDOUT, event); +// return ResponseEntity.ok("Event published successfully"); +// } +// +// @GetMapping("/testPublishWarehouseStockReservedEvent/{id}") +// public ResponseEntity testPublishWarehouseStockReservedEvent(@PathVariable final UUID id) { +// LOGGER.info("Testing Event Publisher"); +// +// WarehouseStockReservedEvent event = new WarehouseStockReservedEvent( +// id.toString()); +// eventPublisher.publishEvent(EventsConstants.WAREHOUSE_STOCK_RESERVED, event); +// return ResponseEntity.ok("Event published successfully"); +// } +// +// @GetMapping("/testPublishWarehouseOrderFulfillmentFailedEvent/{id}") +// public ResponseEntity testWarehouseOrderFulfillmentFailedEvent(@PathVariable final UUID id) { +// LOGGER.info("Testing Event Publisher"); +// +// WarehouseOrderFulfillmentFailedEvent event = new WarehouseOrderFulfillmentFailedEvent( +// id.toString(), "Order Fulfillment Failed"); +// eventPublisher.publishEvent(EventsConstants.WAREHOUSE_ORDER_FULFILLMENT_FAILED, event); +// return ResponseEntity.ok("Event published successfully"); +// } +// +// @GetMapping("/testOrderAssignedToCourierEvent/{id}") +// public ResponseEntity testOrderAssignedToCourierEvent(@PathVariable final UUID id) { +// LOGGER.info("Testing Event Publisher"); +// +// OrderAssignedToCourierEvent event = new OrderAssignedToCourierEvent( +// id.toString(), UUID.randomUUID().toString(), new BigDecimal(150.9), 10.0, 20.0, "signature", +// ConfirmationType.SIGNATURE); +// eventPublisher.publishEvent(EventsConstants.ORDER_ASSIGNED_TO_COURIER, event); +// return ResponseEntity.ok("Event published successfully"); +// } +// +// @GetMapping("/testOrderDeliveredEvent/{id}/{courierId}") +// public ResponseEntity testOrderDeliveredEvent(@PathVariable final UUID id, +// @PathVariable final String courierId) { +// LOGGER.info("Testing Event Publisher"); +// +// OrderDeliveredEvent event = new OrderDeliveredEvent( +// id.toString(), courierId.toString(), new BigDecimal(150.9)); +// eventPublisher.publishEvent(EventsConstants.ORDER_DELIVERED, event); +// return ResponseEntity.ok("Event published successfully"); +// } +// +// @GetMapping("/testOrderOutForDeliveryEvent/{id}/{courierId}") +// public ResponseEntity testOrderOutForDeliveryEvent(@PathVariable final UUID id, +// @PathVariable final String courierId) { +// LOGGER.info("Testing Event Publisher"); +// +// OrderOutForDeliveryEvent event = new OrderOutForDeliveryEvent( +// id.toString(), courierId.toString()); +// eventPublisher.publishEvent(EventsConstants.ORDER_OUT_FOR_DELIVERY, event); +// return ResponseEntity.ok("Event published successfully"); +// } +// +// @GetMapping("/testOrderPackagedEvent/{id}") +// public ResponseEntity testOrderPackagedEvent(@PathVariable final UUID id) { +// LOGGER.info("Testing Event Publisher"); +// +// OrderPackagedEvent event = new OrderPackagedEvent( +// id.toString()); +// eventPublisher.publishEvent(EventsConstants.ORDER_PACKAGED, event); +// return ResponseEntity.ok("Event published successfully"); +// } +// +// @GetMapping("/testOrderDeliveryFailedEvent/{id}/{courierId}") +// public ResponseEntity testOrderDeliveryFailedEvent(@PathVariable final UUID id, +// @PathVariable final UUID courierId) { +// LOGGER.info("Testing Event Publisher"); +// +// OrderDeliveryFailedEvent event = new OrderDeliveryFailedEvent( +// id.toString(), courierId.toString(), "Delivery failed"); +// eventPublisher.publishEvent(EventsConstants.ORDER_DELIVERY_FAILED, event); +// return ResponseEntity.ok("Event published successfully"); +// } +// +//} diff --git a/src/main/java/com/podzilla/order/messaging/OrderConsumer.java b/src/main/java/com/podzilla/order/messaging/OrderConsumer.java index 13e8225..b9491da 100644 --- a/src/main/java/com/podzilla/order/messaging/OrderConsumer.java +++ b/src/main/java/com/podzilla/order/messaging/OrderConsumer.java @@ -100,9 +100,9 @@ private void handleWarehouseOrderFulfillmentFailedEvent( log.info("❌ Order fulfillment failed for order: {}, reason: {}", warehouseOrderFulfillmentFailedEvent.getOrderId(), warehouseOrderFulfillmentFailedEvent.getReason()); - orderService.cancelOrder( + orderService.updateOrderStatus( UUID.fromString(warehouseOrderFulfillmentFailedEvent.getOrderId()), - warehouseOrderFulfillmentFailedEvent.getReason()); + OrderStatus.FULFILLMENT_FAILED); } private void handleCartCheckoutEvent( diff --git a/src/main/java/com/podzilla/order/model/Address.java b/src/main/java/com/podzilla/order/model/Address.java index 6c47cd7..b070c68 100644 --- a/src/main/java/com/podzilla/order/model/Address.java +++ b/src/main/java/com/podzilla/order/model/Address.java @@ -1,7 +1,14 @@ package com.podzilla.order.model; -import jakarta.persistence.*; +import com.fasterxml.jackson.annotation.JsonIgnore; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.OneToOne; +import jakarta.persistence.Table; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @@ -26,6 +33,7 @@ public class Address { private String postalCode; @OneToOne + @JsonIgnore @JoinColumn(name = "order_id", nullable = false) private Order order; } diff --git a/src/main/java/com/podzilla/order/model/Order.java b/src/main/java/com/podzilla/order/model/Order.java index 902a1b4..5014677 100644 --- a/src/main/java/com/podzilla/order/model/Order.java +++ b/src/main/java/com/podzilla/order/model/Order.java @@ -1,6 +1,7 @@ package com.podzilla.order.model; +import com.fasterxml.jackson.annotation.JsonIgnore; import jakarta.persistence.Table; import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; @@ -42,6 +43,7 @@ public class Order { private BigDecimal totalAmount; @OneToOne(cascade = CascadeType.ALL) + @JsonIgnore private Address shippingAddress; @Enumerated(EnumType.STRING) @@ -61,6 +63,7 @@ public class Order { @OneToMany(mappedBy = "order", cascade = CascadeType.ALL, orphanRemoval = true) + @JsonIgnore private List orderProducts = new ArrayList<>(); public static class Builder { diff --git a/src/main/java/com/podzilla/order/model/OrderProduct.java b/src/main/java/com/podzilla/order/model/OrderProduct.java index dad2e31..20913bf 100644 --- a/src/main/java/com/podzilla/order/model/OrderProduct.java +++ b/src/main/java/com/podzilla/order/model/OrderProduct.java @@ -1,5 +1,6 @@ package com.podzilla.order.model; +import com.fasterxml.jackson.annotation.JsonIgnore; import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; @@ -39,6 +40,7 @@ public class OrderProduct { private BigDecimal pricePerUnit; @ManyToOne(fetch = FetchType.LAZY) + @JsonIgnore @JoinColumn(name = "order_id", nullable = false) private Order order; } diff --git a/src/main/java/com/podzilla/order/service/OrderService.java b/src/main/java/com/podzilla/order/service/OrderService.java index 57c3c50..7edd7a6 100644 --- a/src/main/java/com/podzilla/order/service/OrderService.java +++ b/src/main/java/com/podzilla/order/service/OrderService.java @@ -16,11 +16,13 @@ import com.podzilla.order.service.statusstrategy.OrderStatusStrategy; import com.podzilla.order.service.statusstrategy.OrderStatusStrategyFactory; import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.BeanUtils; +import org.springframework.beans.BeanWrapper; +import org.springframework.beans.BeanWrapperImpl; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.web.reactive.function.client.WebClient; + import java.time.LocalDateTime; import java.util.List; import java.util.Optional; @@ -110,9 +112,9 @@ public Order updateOrder(final UUID id, final Order updatedOrder) { Optional existingOrder = orderRepository.findById(id); if (existingOrder.isPresent()) { Order order = existingOrder.get(); - BeanUtils.copyProperties(updatedOrder, order, "id"); + copyNonNullProperties(updatedOrder, order); order.setUpdatedAt(LocalDateTime.now()); - log.info("Order with id: {} was found and updated", id); + log.info("Order with id: {} was found and updated to status: {}", id, updatedOrder.getStatus()); return orderRepository.save(order); } log.warn("Order with id: {} was not found", id); @@ -170,7 +172,7 @@ public Order cancelOrder(final UUID id, final String reason) { public Order updateOrderStatus(final UUID id, final OrderStatus status) { - log.info("Updating order status with ID: {}", id); + log.info("Updating order status with ID: {} to status: {}", id, status); Optional existingOrder = orderRepository.findById(id); @@ -219,4 +221,18 @@ private List getOrderItems(final Order order) { product.getPricePerUnit())) .toList(); } + + public void copyNonNullProperties(final Object src, final Object target) { + BeanWrapper srcWrap = new BeanWrapperImpl(src); + BeanWrapper trgWrap = new BeanWrapperImpl(target); + + for (java.beans.PropertyDescriptor descriptor : srcWrap.getPropertyDescriptors()) { + String propertyName = descriptor.getName(); + Object propertyValue = srcWrap.getPropertyValue(propertyName); + + if (propertyValue != null && trgWrap.isWritableProperty(propertyName)) { + trgWrap.setPropertyValue(propertyName, propertyValue); + } + } + } }