CustomerOrder.java

package com.dmasone.identity.orders.domain;

import java.time.Instant;
import java.util.Objects;
import java.util.UUID;

/**
 * Order aggregate for the placement use case. The aggregate captures the
 * customer's purchase intent after catalog has enough information to reserve
 * stock for the requested product.
 */
public final class CustomerOrder {

    private final UUID id;
    private final Long productId;
    private final int quantity;
    private final OrderStatus status;
    private final Instant createdAt;
    private final String idempotencyKey;

    private CustomerOrder(
            UUID id,
            Long productId,
            int quantity,
            OrderStatus status,
            Instant createdAt,
            String idempotencyKey
    ) {
        this.id = Objects.requireNonNull(id, "id must not be null");
        if (productId == null) {
            throw new InvalidOrderException("Product id is required");
        }
        this.productId = productId;
        if (quantity <= 0) {
            throw new InvalidOrderException("Order quantity must be greater than zero");
        }
        this.quantity = quantity;
        this.status = Objects.requireNonNull(status, "status must not be null");
        this.createdAt = Objects.requireNonNull(createdAt, "createdAt must not be null");
        this.idempotencyKey = idempotencyKey;
    }

    public static CustomerOrder place(
            UUID id,
            Long productId,
            int quantity,
            Instant createdAt,
            String idempotencyKey
    ) {
        return new CustomerOrder(id, productId, quantity, OrderStatus.PLACED, createdAt, idempotencyKey);
    }

    public static CustomerOrder restore(
            UUID id,
            Long productId,
            int quantity,
            OrderStatus status,
            Instant createdAt,
            String idempotencyKey
    ) {
        return new CustomerOrder(id, productId, quantity, status, createdAt, idempotencyKey);
    }

    public UUID id() {
        return id;
    }

    public Long productId() {
        return productId;
    }

    public int quantity() {
        return quantity;
    }

    public OrderStatus status() {
        return status;
    }

    public Instant createdAt() {
        return createdAt;
    }

    public String idempotencyKey() {
        return idempotencyKey;
    }
}