ShipmentContainer.java

package com.tradecloud.domain.container;

import com.tradecloud.domain.demurrage.OverstayAndStorageTransaction;
import com.tradecloud.domain.demurrage.TurnInTransaction;
import com.tradecloud.domain.model.shipment.ShippingMode;
import com.tradecloud.domain.party.ServiceProvider;
import com.tradecloud.domain.place.Depot;
import com.tradecloud.domain.place.FinalDestination;
import com.tradecloud.domain.place.PlaceOfDischarge;
import com.tradecloud.domain.shipment.MultiModalShipment;
import com.tradecloud.domain.shipment.PlaceAddress;
import com.tradecloud.domain.shipment.Shipment;
import com.tradecloud.domain.shipment.ShipmentShippingInfo;
import lombok.Getter;
import lombok.Setter;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.hibernate.annotations.ForeignKey;

import javax.persistence.*;
import javax.validation.constraints.NotNull;
import javax.xml.bind.annotation.*;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Date;
import java.util.Optional;

/**
 * https://connect.devstream.net/display/Dev/Container+Fields.
 */
@Entity
@NamedQueries({
        @NamedQuery(name = "shipmentContainer.findByShipment",
                query = "from ShipmentContainer where shipment = :shipment order by id"),
        @NamedQuery(name = "shipmentContainer.findByShipmentWithOverstayAndStorageTransaction",
                query = "from ShipmentContainer where shipment = :shipment and overstayAndStorageTransaction is not null"),
        @NamedQuery(name = "shipmentContainer.findByShipmentWithTurnInTransaction",
                query = "from ShipmentContainer where shipment = :shipment and turnInTransaction is not null"),
        @NamedQuery(name = "shipmentContainer.findWithElapsedOverstayAndStorageFreePeriod",
                query = "from ShipmentContainer where overstayAndStorageFreePeriodEnd < :currentDate and containerDates.carrierReleaseDate is null"),
        @NamedQuery(name = "shipmentContainer.findWithElapsedTurnInFreePeriod",
                query = "from ShipmentContainer where turnInFreePeriodEnd < :currentDate and containerDates.turnInDate is null")})
@DiscriminatorValue("SHIPMENT")
@Access(AccessType.FIELD)
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "ShipmentContainer")
@Getter
@Setter
public class ShipmentContainer extends Container {

    private static final long serialVersionUID = 1L;

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "shipment_id")
    @XmlTransient
    private Shipment shipment;

    @ManyToOne(fetch = FetchType.EAGER)
    @XmlTransient
    private MultiModalShipment modalShipment;

    /*
     * Used when a values on a shipment are updated, and you still need access to values before the update.
     */
    @Transient
    private Shipment oldShipment;

    private BigInteger uniqueNumber;

    /**
     * The unique reference for a container.  The same container can be used on different shipments.
     * Ensure that the container reference for sea shipments has the following format: 4 alpha followed by 7 numeric values
     * (this is client-dependent).
     * The reference should be blank when adding or defaulting containers on a shipment and a user is forced to capture a reference before the
     * containers can be saved.
     */
    @XmlElement
    @NotNull(message = "ShipmentContainer reference is required")
    private String reference;

    @XmlElement
    private String sealReference;

    @XmlElement
    private String additionalSealReference;

//    @ManyToOne
//    @ForeignKey(name = "fk_placeofdischarge")
//    @XmlElement(name = "PlaceOfDischarge")
//    private PlaceOfDischarge placeOfDischarge;

    @ManyToOne
    @ForeignKey(name = "fk_clearingdepot")
    @XmlElement(name = "ClearingDepot")
    private Depot clearingDepot;

    @ManyToOne
    @ForeignKey(name = "fk_transporter")
    @XmlElement(name = "Transporter")
    private ServiceProvider transporter;

    @ManyToOne
    @ForeignKey(name = "fk_turninclearingdepot")
    @XmlElement(name = "TurnInClearingDepot")
    private Depot turnInDepot;

    @ManyToOne
    @ForeignKey(name = "fk_finaldestination")
    private FinalDestination finalDestination;

    @XmlElement
    private BigDecimal daysStored;

    @XmlElement
    private BigDecimal tareWeight;

    @XmlElement
    private BigDecimal netWeight;

    @XmlElement
    private BigDecimal grossWeight;

    @XmlElement
    private BigDecimal grossVolume;

    @XmlElement
    private boolean stoppedByCustoms;

    @XmlElement
    private boolean customsStopUnpacked;

    @XmlElement
    private boolean normalTurnIn;

    // Demurrage

    @XmlAttribute
    @Temporal(TemporalType.TIMESTAMP)
    private Date overstayAndStorageFreePeriodEnd;

    @OneToOne(cascade = CascadeType.ALL, orphanRemoval = true)
    @ForeignKey(name = "fk_overstayandstoragetransaction")
    private OverstayAndStorageTransaction overstayAndStorageTransaction;

    @XmlAttribute
    @Temporal(TemporalType.TIMESTAMP)
    private Date turnInFreePeriodEnd;

    @OneToOne(cascade = CascadeType.ALL, orphanRemoval = true)
    @ForeignKey(name = "fk_turnintransaction")
    private TurnInTransaction turnInTransaction;

    @Enumerated(EnumType.STRING)
    private ShippingMode transporterShippingMode;

    private PlaceAddress unpackDepot;
    private boolean overriddenWeight;

    @Transient
    private Long transporterId;

    /**
     * Constructors, one for normal use, one for hibernate.
     */
    public ShipmentContainer(ContainerType containerType) {
        super(containerType);
    }

    public ShipmentContainer(ContainerType containerType, BigDecimal quantity) {
        super(containerType, quantity);
    }

    public ShipmentContainer() {
    }

    //copy constructor
    public ShipmentContainer(ShipmentContainer toCopy) {
        super(toCopy.getContainerType(), toCopy.getQuantity());
        this.additionalSealReference = toCopy.getAdditionalSealReference();
        this.cartonsPerContainer = toCopy.getCartonsPerContainer();
        this.clearingDepot = toCopy.getClearingDepot();
        this.customsStopUnpacked = toCopy.isCustomsStopUnpacked();
        this.daysStored = toCopy.getDaysStored();
        this.finalDestination = toCopy.getFinalDestination();
        this.grossVolume = toCopy.getGrossVolume();
        this.grossWeight = toCopy.getGrossWeight();
        this.netWeight = toCopy.getNetWeight();
        this.normalTurnIn = toCopy.isNormalTurnIn();
        this.overstayAndStorageFreePeriodEnd = toCopy.getOverstayAndStorageFreePeriodEnd();
        this.overstayAndStorageTransaction = toCopy.getOverstayAndStorageTransaction();
        this.reference = toCopy.getReference();
        this.sealReference = toCopy.getSealReference();
        this.shipment = toCopy.getShipment();
        this.stoppedByCustoms = toCopy.isStoppedByCustoms();
        this.tareWeight = toCopy.getTareWeight();
        this.turnInDepot = toCopy.getTurnInDepot();
        this.turnInFreePeriodEnd = toCopy.getTurnInFreePeriodEnd();
        this.turnInTransaction = toCopy.getTurnInTransaction();
        this.unpackDepot = toCopy.getUnpackDepot();
    }

    public Shipment getShipment() {
        return shipment;
    }

    public void setShipment(Shipment shipment) {
        this.shipment = shipment;
    }

    public String getSealReference() {
        return sealReference;
    }

    public String getReference() {
        return reference;
    }

    public void setReference(String reference) {
        this.reference = reference;
    }

    public PlaceOfDischarge getPlaceOfDischarge() {
        return Optional.ofNullable(getShipment()).map(Shipment::getShippingInfo)
                .map(ShipmentShippingInfo::getPlaceOfDischarge).orElse(null);
    }

//    public void setPlaceOfDischarge(PlaceOfDischarge placeOfDischarge) {
//        this.placeOfDischarge = placeOfDischarge;
//    }

    public Depot getClearingDepot() {
        return clearingDepot;
    }

    public void setClearingDepot(Depot clearingDepot) {
        this.clearingDepot = clearingDepot;
    }

    public ServiceProvider getTransporter() {
        return transporter;
    }

    public void setTransporter(ServiceProvider transporter) {
        this.transporter = transporter;
    }

    public Depot getTurnInDepot() {
        return turnInDepot;
    }

    public void setTurnInDepot(Depot turnInDepot) {
        this.turnInDepot = turnInDepot;
    }

    public FinalDestination getFinalDestination() {
        return finalDestination;
    }

    public void setFinalDestination(FinalDestination finalDestination) {
        this.finalDestination = finalDestination;
    }

    public BigDecimal getDaysStored() {
        return daysStored;
    }

    public void setDaysStored(BigDecimal daysStored) {
        this.daysStored = daysStored;
    }

    public BigDecimal getTareWeight() {
        if (tareWeight == null || tareWeight.compareTo(BigDecimal.ZERO) == 0) {
            ContainerType containerType = getContainerType();
            tareWeight = containerType != null ? containerType.getTareWeight() : BigDecimal.ZERO;
        }
        return tareWeight;
    }

    public void setTareWeight(BigDecimal tareWeight) {
        this.tareWeight = tareWeight;
    }

    public BigDecimal getNetWeight() {
        return netWeight;
    }

    public void setNetWeight(BigDecimal netWeight) {
        this.netWeight = netWeight;
        if (netWeight != null && tareWeight != null) {
            this.grossWeight = netWeight.add(tareWeight);
        }
    }

    public BigDecimal getGrossWeight() {
        return grossWeight;
    }

    public void setGrossWeight(BigDecimal grossWeight) {
        this.grossWeight = grossWeight;
    }

    public BigDecimal getGrossVolume() {
        return grossVolume;
    }

    public void setGrossVolume(BigDecimal grossVolume) {
        this.grossVolume = grossVolume;
    }

    public boolean isStoppedByCustoms() {
        return stoppedByCustoms;
    }

    public void setStoppedByCustoms(boolean stoppedByCustoms) {
        this.stoppedByCustoms = stoppedByCustoms;
    }

    public boolean isCustomsStopUnpacked() {
        return customsStopUnpacked;
    }

    public void setCustomsStopUnpacked(boolean customsStopUnpacked) {
        this.customsStopUnpacked = customsStopUnpacked;
    }

    public boolean isNormalTurnIn() {
        return normalTurnIn;
    }

    public void setNormalTurnIn(boolean normalTurnIn) {
        this.normalTurnIn = normalTurnIn;
    }

    public void setSealReference(String sealReference) {
        this.sealReference = sealReference;
    }

    public String getAdditionalSealReference() {
        return additionalSealReference;
    }

    public void setAdditionalSealReference(String additionalSealReference) {
        this.additionalSealReference = additionalSealReference;
    }

    public Date getOverstayAndStorageFreePeriodEnd() {
        return overstayAndStorageFreePeriodEnd;
    }

    public void setOverstayAndStorageFreePeriodEnd(Date overstayAndStorageFreePeriodEnd) {
        this.overstayAndStorageFreePeriodEnd = overstayAndStorageFreePeriodEnd;
    }

    public Date getTurnInFreePeriodEnd() {
        return turnInFreePeriodEnd;
    }

    public void setTurnInFreePeriodEnd(Date turnInFreePeriodEnd) {
        this.turnInFreePeriodEnd = turnInFreePeriodEnd;
    }

    @Override
    public int hashCode() {
        return new HashCodeBuilder().appendSuper(super.hashCode()).append(reference).toHashCode();
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (!(obj instanceof Container)) {
            return false;
        }
        ShipmentContainer other = (ShipmentContainer) obj;
        return new EqualsBuilder().appendSuper(super.equals(obj)).append(reference, other.reference).append(uniqueNumber,
                other.uniqueNumber).append(id, other.id).isEquals();
    }

    public OverstayAndStorageTransaction getOverstayAndStorageTransaction() {
        return overstayAndStorageTransaction;
    }

    public void setOverstayAndStorageTransaction(OverstayAndStorageTransaction overstayAndStorageTransaction) {
        this.overstayAndStorageTransaction = overstayAndStorageTransaction;
    }

    public TurnInTransaction getTurnInTransaction() {
        return turnInTransaction;
    }

    public void setTurnInTransaction(TurnInTransaction turnInTransaction) {
        this.turnInTransaction = turnInTransaction;
    }

    public Shipment getOldShipment() {
        return oldShipment;
    }

    public void setOldShipment(Shipment oldShipment) {
        this.oldShipment = oldShipment;
    }

    public ShippingMode getTransporterShippingMode() {
        return transporterShippingMode;
    }

    public void setTransporterShippingMode(ShippingMode transporterShippingMode) {
        this.transporterShippingMode = transporterShippingMode;
    }

    @Override
    public String toString() {
        return "ShipmentContainer{" +
                "shipment=" + shipment +
                ", oldShipment=" + oldShipment +
                ", reference='" + reference + '\'' +
                ", sealReference='" + sealReference + '\'' +
                ", additionalSealReference='" + additionalSealReference + '\'' +

                ", clearingDepot=" + clearingDepot +
                ", transporter=" + transporter +
                ", turnInDepot=" + turnInDepot +
                ", finalDestination=" + finalDestination +
                ", daysStored=" + daysStored +
                ", cartonsPerContainer=" + cartonsPerContainer +
                ", tareWeight=" + tareWeight +
                ", netWeight=" + netWeight +
                ", grossWeight=" + grossWeight +
                ", grossVolume=" + grossVolume +
                ", stoppedByCustoms=" + stoppedByCustoms +
                ", customsStopUnpacked=" + customsStopUnpacked +
                ", normalTurnIn=" + normalTurnIn +
                ", overstayAndStorageFreePeriodEnd=" + overstayAndStorageFreePeriodEnd +
                ", overstayAndStorageTransaction=" + overstayAndStorageTransaction +
                ", turnInFreePeriodEnd=" + turnInFreePeriodEnd +
                ", turnInTransaction=" + turnInTransaction +
                '}';
    }

    public void setUniqueNumber(BigInteger uniqueNumber) {
        this.uniqueNumber = uniqueNumber;
    }

    public BigInteger getUniqueNumber() {
        return uniqueNumber;
    }

    public PlaceAddress getUnpackDepot() {
        return unpackDepot;
    }

    public void setUnpackDepot(PlaceAddress unpackDepot) {
        this.unpackDepot = unpackDepot;
    }

    @Override
    public boolean isShipmentContainer() {
        return true;
    }

    public BigDecimal getTotalContainerWeight() {
        if (getContainerType() != null && getContainerType().getTareWeight() != null && getGrossWeight() != null) {
            return getGrossWeight().add(getContainerType().getTareWeight());
        }
        return BigDecimal.ZERO;
    }

    public boolean isOverriddenWeight() {
        return overriddenWeight;
    }

    public void setOverriddenWeight(boolean overriddenWeight) {
        this.overriddenWeight = overriddenWeight;
    }

    public void setTransporterId(Long transporterId) {
        this.transporterId = transporterId;
    }

    public Long getTransporterId() {
        return transporterId;
    }
}