OrderDtos.java
package com.rbctcsworld.ecommerce.order;
import jakarta.validation.Valid;
import jakarta.validation.constraints.Size;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
public final class OrderDtos {
private OrderDtos() {
}
/**
* Body of POST /api/orders and POST /api/checkout/quote. The quote ignores the address; placing an order
* needs one (400 "Shipping address is required" otherwise).
*/
public record CheckoutRequest(@Size(max = 40) String couponCode, @Valid ShippingAddress shippingAddress) {
}
public record OrderLine(Long productId, String sku, String name, BigDecimal unitPrice,
int quantity, BigDecimal lineTotal) {
}
/** "Review your order" page: what the customer WOULD pay. Nothing is saved or reserved. */
public record QuoteResponse(List<OrderLine> items, int totalQuantity, BigDecimal subtotal, String couponCode,
BigDecimal discount, BigDecimal shippingFee, BigDecimal tax, BigDecimal total) {
}
public record OrderResponse(Long id, String orderNumber, Long customerId, String status,
List<OrderLine> items, int totalQuantity, BigDecimal subtotal,
String couponCode, BigDecimal discount, BigDecimal shippingFee,
BigDecimal tax, BigDecimal total, String carrier, String trackingNumber,
LocalDateTime createdAt, LocalDateTime paidAt, LocalDateTime shippedAt,
LocalDateTime deliveredAt, LocalDateTime cancelledAt,
ShippingAddress shippingAddress) {
public static OrderResponse from(CustomerOrder o) {
List<OrderLine> lines = o.getItems().stream()
.map(i -> new OrderLine(i.getProductId(), i.getSku(), i.getProductName(),
i.getUnitPrice(), i.getQuantity(), i.getLineTotal()))
.toList();
return new OrderResponse(o.getId(), o.getOrderNumber(), o.getUserId(), o.getStatus(), lines,
o.getTotalItems(), o.getSubtotal(), o.getCouponCode(), o.getDiscount(), o.getShippingFee(),
o.getTax(), o.getTotal(), o.getCarrier(), o.getTrackingNumber(), o.getCreatedAt(),
o.getPaidAt(), o.getShippedAt(), o.getDeliveredAt(), o.getCancelledAt(), o.getShippingAddress());
}
}
public record TrackingEvent(String status, String note, LocalDateTime at) {
}
/**
* Tracking view. Deliberately contains NO customer id, email, address, prices or items, because the same shape
* is served by the PUBLIC endpoint GET /api/tracking/{trackingNumber}.
*/
public record TrackingResponse(String orderNumber, String status, String carrier, String trackingNumber,
List<TrackingEvent> events) {
public static TrackingResponse from(CustomerOrder o) {
return new TrackingResponse(o.getOrderNumber(), o.getStatus(), o.getCarrier(), o.getTrackingNumber(),
o.getEvents().stream().map(e -> new TrackingEvent(e.getStatus(), e.getNote(), e.getCreatedAt())).toList());
}
}
}