ShippingOrderVO.java

/*
 * Copyright 2005-2025 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.openwms.wms.shipping.api;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonManagedReference;
import com.fasterxml.jackson.annotation.JsonProperty;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
import org.ameba.http.AbstractBase;

import java.io.Serializable;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.StringJoiner;

/**
 * A ShippingOrderVO is the envelope that represents a customer order and stores some general information along the order positions.
 *
 * @author Heiko Scherrer
 */
@JsonInclude(JsonInclude.Include.NON_EMPTY)
public class ShippingOrderVO extends AbstractBase<ShippingOrderVO> implements Serializable {

    public static final String MEDIA_TYPE = "application/vnd.openwms.shipping-order-v1+json";

    /** The persistent identifier. */
    @JsonProperty("pKey")
    private String pKey;
    /** The unique order ID. */
    @NotBlank(message = "{owms.wms.shp.orderId}", groups = ValidationGroups.Create.class)
    @JsonProperty("orderId")
    private String orderId;
    /** A reference to the customers order number. */
    @JsonProperty("customerOrderId")
    private String customerOrderId;
    /** A customer number. */
    @JsonProperty("customerNo")
    private String customerNo;
    /** Current state of this Order. */
    @JsonProperty("state")
    private String orderState;
    /**
     * How the ShippingOrder should be processed:
     * <ul>
     *     <li>MANUAL: Manual processing means just creation no further processing</li>
     *     <li>AUTOMATIC: Orders are created and processed directly</li>
     * </ul>
     */
    @JsonProperty("startMode")
    private String startMode;
    /** Some arbitrary shipping type, like DHL, FedEx etc. */
    @JsonProperty("shippingType")
    private String shippingType;
    /** An intermediate or final target destination for the ShippingOrder that is used in the allocation strategy. */
    @JsonProperty("shipTo")
    private String shipTo;
    /** A priority for processing order. */
    @JsonProperty("priority")
    private Integer priority;
    /** Timestamp until when the order needs to be processed (time of shipping can be different). */
    @JsonProperty("latestDueDate")
    private ZonedDateTime latestDueDate;
    /** Timestamp when the Order should be started earliest. */
    @JsonProperty("startDate")
    private ZonedDateTime startDate;
    /** A list of positions. */
    @Size(min = 1, message = "{owms.wms.shp.positions}", groups = ValidationGroups.Create.class)
    @JsonProperty("positions")
    @JsonManagedReference
    private List<@Valid BaseShippingOrderPositionVO> positions = new ArrayList<>(0);
    /** Arbitrary detail information stored along an order. */
    @JsonProperty("details")
    private Map<String, String> details = new HashMap<>();

    /*~-------------------- constructors --------------------*/
    @JsonCreator
    private ShippingOrderVO() {}

    public ShippingOrderVO(String orderId) {
        this.orderId = orderId;
    }

    /*~-------------------- accessors --------------------*/

    public String getpKey() {
        return pKey;
    }

    public boolean hasPKey() {
        return pKey != null && !pKey.isEmpty();
    }

    public void setpKey(String pKey) {
        this.pKey = pKey;
    }

    public String getOrderId() {
        return orderId;
    }

    public boolean hasOrderId() {
        return orderId != null && !orderId.isEmpty();
    }

    public String getCustomerOrderId() {
        return customerOrderId;
    }

    public void setCustomerOrderId(String customerOrderId) {
        this.customerOrderId = customerOrderId;
    }

    public String getCustomerNo() {
        return customerNo;
    }

    public void setCustomerNo(String customerNo) {
        this.customerNo = customerNo;
    }

    public String getOrderState() {
        return orderState;
    }

    public boolean hasOrderState() {
        return orderState != null && !orderState.isEmpty();
    }

    public void setOrderState(String orderState) {
        this.orderState = orderState;
    }

    public String getStartMode() {
        return startMode;
    }

    public String getShippingType() {
        return shippingType;
    }

    public void setShippingType(String shippingType) {
        this.shippingType = shippingType;
    }

    public Integer getPriority() {
        return priority;
    }

    public boolean hasPriority() {
        return priority != null;
    }

    public ZonedDateTime getLatestDueDate() {
        return latestDueDate;
    }

    public void setStartMode(String startMode) {
        this.startMode = startMode;
    }

    public void setPriority(Integer priority) {
        this.priority = priority;
    }

    public void setLatestDueDate(ZonedDateTime latestDueDate) {
        this.latestDueDate = latestDueDate;
    }

    public void setStartDate(ZonedDateTime startDate) {
        this.startDate = startDate;
    }

    public void setOrderId(String orderId) {
        this.orderId = orderId;
    }

    public String getShipTo() {
        return shipTo;
    }

    public void setShipTo(String shipTo) {
        this.shipTo = shipTo;
    }

    public ZonedDateTime getStartDate() {
        return startDate;
    }

    public List<BaseShippingOrderPositionVO> getPositions() {
        return positions;
    }

    public void setPositions(List<BaseShippingOrderPositionVO> positions) {
        this.positions = positions;
        this.positions.forEach(p -> {
            p.setOrderId(this.orderId);
            p.setOrderPKey(this.pKey);
        });
    }

    public Map<String, String> getDetails() {
        return details;
    }

    public void setDetails(Map<String, String> details) {
        this.details = details;
    }

    public boolean hasStartMode() {
        return this.startMode != null && !this.startMode.isEmpty();
    }

    public boolean hasLatestDueDate() {
        return this.latestDueDate != null;
    }

    public boolean hasStartDate() {
        return this.startDate != null;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        if (!super.equals(o)) return false;
        ShippingOrderVO that = (ShippingOrderVO) o;
        return Objects.equals(pKey, that.pKey) &&
                Objects.equals(orderId, that.orderId) &&
                Objects.equals(customerNo, that.customerNo) &&
                Objects.equals(orderState, that.orderState) &&
                Objects.equals(startMode, that.startMode) &&
                Objects.equals(shippingType, that.shippingType) &&
                Objects.equals(priority, that.priority) &&
                Objects.equals(latestDueDate, that.latestDueDate) &&
                Objects.equals(startDate, that.startDate) &&
                Objects.equals(positions, that.positions) &&
                Objects.equals(details, that.details);
    }

    @Override
    public int hashCode() {
        return Objects.hash(super.hashCode(), pKey, orderId, customerNo, orderState, startMode, shippingType, priority, latestDueDate, startDate, positions, details);
    }

    @Override
    public String toString() {
        return new StringJoiner(", ", ShippingOrderVO.class.getSimpleName() + "[", "]")
                .add("pKey='" + pKey + "'")
                .add("orderId='" + orderId + "'")
                .add("customerNo='" + customerNo + "'")
                .add("orderState='" + orderState + "'")
                .add("startMode='" + startMode + "'")
                .add("shippingType='" + shippingType + "'")
                .add("shipTo='" + shipTo + "'")
                .add("priority=" + priority)
                .add("latestDueDate=" + latestDueDate)
                .add("startDate=" + startDate)
                .add("positions=" + positions)
                .add("details=" + details)
                .toString();
    }
}