ClearingInstruction.java

package com.tradecloud.domain.shipment.clearing;

import com.tradecloud.converter.StringListAttributeConverter;
import com.tradecloud.domain.configuration.clearing.za.PurposeCode;
import com.tradecloud.domain.dms.DocumentManagementHardCoding;
import com.tradecloud.domain.sars.Status;
import com.tradecloud.domain.shipment.MultiModalShipment;
import lombok.Getter;
import lombok.Setter;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;
import org.hibernate.annotations.JoinFormula;

import javax.persistence.*;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Entity
@Access(AccessType.FIELD)
@Getter
@Setter
public class ClearingInstruction extends BaseClearingInstruction implements Cloneable {

    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    @Fetch(value = FetchMode.SUBSELECT)
    @XmlElementWrapper(name = "ClearingEvents")
    @XmlElement(name = "ClearingEvent")
    @OrderBy("createDateTime")
    protected List<ClearingEvent> events = new LinkedList();

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinFormula("(SELECT MAX(clearinginstruction_clearingevent.events_id) " +
            "FROM clearinginstruction_clearingevent left join ClearingEvent on clearinginstruction_clearingevent.events_id = ClearingEvent.id " +
            "WHERE clearinginstruction_clearingevent.ClearingInstruction_id = id)")
    protected ClearingEvent lastEvent;

    @Column(name = "clearingDocumentTypes")
    @Convert(converter = StringListAttributeConverter.class)
    private Set<String> clearingDocumentTypes;

    @Enumerated(value = EnumType.STRING)
    @ElementCollection(targetClass = PurposeCode.class)
    @CollectionTable(name = "ClearingInstructionPurposeCode")
    @Column(name = "purposeCode")
    private Set<PurposeCode> purposeCodes;
    private Integer version;
    private BigDecimal priceOfGoods;
    private BigDecimal originalPriceOfGoods;

    @Enumerated(EnumType.STRING)
    protected FileType fileType;

    @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true)
    private Set<AdditionalClearingInfo> additionalClearingInfo = new HashSet();
    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true)
    private Set<AdvancedPayment> advancedPayments = new HashSet<>();

    private static final long serialVersionUID = 1L;

    @OneToOne
    private MultiModalShipment multiModalShipment;

    public Set<PurposeCode> getPurposeCodes() {
        return purposeCodes;
    }

    public void setPurposeCodes(Set<PurposeCode> purposeCodes) {
        this.purposeCodes = purposeCodes;
    }

    public ClearingEvent getLastStatus() {
        return lastEvent;
    }

    public List<ClearingEvent> getEvents() {
        if (events == null) {
            events = new LinkedList<>();
        }
        return events;
    }

    @Override
    public ClearingEvent getLastEvent() {
        return lastEvent;
    }

    public void setEvents(List<ClearingEvent> events) {
        this.events = events;
    }

    public void addClearingEvent(ClearingEvent clearingEvent) {
        this.getEvents().add(clearingEvent);
    }

    public Set<String> getClearingDocumentTypes() {
        return clearingDocumentTypes;
    }

    public void setClearingDocumentTypes(Set<String> clearingDocumentTypes) {
        this.clearingDocumentTypes = clearingDocumentTypes;
    }

    public FileType getFileType() {
        return fileType;
    }

    public void setFileType(FileType fileType) {
        this.fileType = fileType;
    }

    public boolean isClearingInstruction() {
        return true;
    }

    @Override
    public String getDocumentGroupName() {
        return DocumentManagementHardCoding.CLEARING_INSTRUCTION.getDocumentManagementHardCodedName();
    }

    public Integer getVersion() {
        return version;
    }

    public void setVersion(Integer version) {
    }

    public void incrementVersion() {
        if (version == null)
            version = Integer.valueOf(1);
        else
            version++;
    }

    public Set<AdditionalClearingInfo> getAdditionalClearingInfo() {
        return additionalClearingInfo;
    }

    public void setAdditionalClearingInfo(Set<AdditionalClearingInfo> additionalClearingInfo) {
        if (this.additionalClearingInfo == null)
            this.additionalClearingInfo = new HashSet<>();
        if (additionalClearingInfo != null) {
            this.additionalClearingInfo.clear();
            this.additionalClearingInfo.addAll(additionalClearingInfo);
        }
    }

    public Set<AdvancedPayment> getAdvancedPayments() {
        if (advancedPayments == null)
            advancedPayments = new HashSet<>();
        return advancedPayments;
    }

    public void setAdvancedPayments(Set<AdvancedPayment> advancedPayments) {
        if (this.advancedPayments == null)
            this.advancedPayments = new HashSet<>();
        if (advancedPayments != null) {
            this.advancedPayments.clear();
            this.advancedPayments.addAll(advancedPayments.stream().limit(5).collect(Collectors.toSet()));
        }
    }

    public void addAdvancedPaymentDTO(AdvancedPayment dto) {
        if (advancedPayments == null)
            advancedPayments = new HashSet<>();
        advancedPayments.add(dto);
    }

    public void addAdditionalClearingInfoDTO(AdditionalClearingInfo dto) {
        if (additionalClearingInfo == null)
            additionalClearingInfo = new HashSet<>();
        additionalClearingInfo.add(dto);
    }

    public Date getSignedOffDate(){
      return   getEvents().stream().filter(ce -> ce.getEventType()== Status.SIGNED_OFF).max(Comparator.comparing(ClearingEvent::getCreateDateTime))
              .map(ClearingEvent::getCreateDateTime).orElse(null);
    }

}