RequestForQuote.java

package com.tradecloud.domain.model.requestforquote;

import com.tradecloud.common.base.PersistenceBase;
import com.tradecloud.domain.common.Incoterm;
import com.tradecloud.domain.event.Event;
import com.tradecloud.domain.event.RequestForQuoteEvent;
import com.tradecloud.domain.model.organisationalunit.OrganisationalUnit;
import com.tradecloud.domain.state.Stateful;
import com.tradecloud.domain.supplier.OrganisationalUnitSupplier;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;
import org.hibernate.annotations.NaturalId;

import javax.persistence.*;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlID;
import java.util.*;
import java.util.stream.Collectors;

@Entity
@Table(name = "requestforquote")
public class RequestForQuote extends PersistenceBase implements Stateful<RequestForQuoteState, RequestForQuoteEvent> {

    public static final String RFQ_REFERENCE_SEQUENCE = "rfq_reference_sequence";

    @XmlID
    @XmlAttribute(required = true)
    @NaturalId
    @NotNull(message = "Reference is required")
    @Size(max = 255)
    protected String reference;

    @NotNull(message = "State is required")
    @Enumerated(EnumType.STRING)
    protected RequestForQuoteState state = RequestForQuoteState.DRAFT;

    @NotNull(message = "RFQ Name is required")
    @Size(max = 255, message = "RFQ Name cannot exceed 255 characters")
    @XmlAttribute(required = true)
    @XmlID
    protected String name;

    @XmlAttribute
    @Column
    protected Date latestShippingDate;

    @XmlAttribute
    @Column
    protected Date creationDate;

    @XmlElement(name = "Incoterm")
    @ManyToOne
    protected Incoterm incoterm;

    @XmlAttribute
    @Column
    protected Date requiredClosureDate;

    @XmlAttribute
    @Column
    protected Date requiredAtDestinationDate;

    @OneToMany(fetch = FetchType.LAZY)
    @JoinTable(name = "requestforquote_organisationalUnits")
    protected List<OrganisationalUnit> organisationalUnits;

    @XmlElementWrapper(name = "RFQOrganisationalUnitSuppliers")
    @XmlElement(name = "RFQOrganisationalUnitSupplier")
    @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
    @JoinTable(name = "requestforquote_rfqorganisationalunitsupplier",
            joinColumns = {@JoinColumn(name = "requestforquote_id")},
            inverseJoinColumns = {@JoinColumn(name = "rfqorganisationalunitsupplier_id")})
    protected List<RFQOrganisationalUnitSupplier> rfqOrganisationalUnitSuppliers;

    @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    @XmlElement(name = "RFQRule", required = true)
    protected RFQRule rfqRule=new RFQRule();

    @XmlElementWrapper(name = "rfqStyles")
    @XmlElement(name = "RFQStyle")
    @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL,orphanRemoval = true)
    @JoinTable(name = "requestforquote_rfqstyle", joinColumns = {@JoinColumn(name = "requestforquote_id")},
            inverseJoinColumns = {@JoinColumn(name = "rfqstyle_id")})
    private List<RFQStyle> rfqStyles=new ArrayList<>();

    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    @JoinTable(name = "requestforquote_requestforquoteevent", joinColumns = {@JoinColumn(name = "requestforquote_id")},
            inverseJoinColumns = {@JoinColumn(name = "events_id")})
    @Fetch(value = FetchMode.SELECT)
    @XmlElementWrapper(name = "RequestForQuoteEvents")
    @XmlElement(name = "RequestForQuoteEvent")
    @OrderBy("createDateTime")
    private List<RequestForQuoteEvent> events = new LinkedList<RequestForQuoteEvent>();

    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY,mappedBy = "requestForQuote")
    @Fetch(value = FetchMode.SELECT)
    @OrderBy("created")
    private List<RFQOrder> rfqOrders= new LinkedList<>();

    private Date stockLevelGenDate;

    @Column
    protected Date branchSubmissionDate;


    private boolean approvedByAllManagers;

    private boolean notSavedChanges=false;

    @OneToMany(fetch = FetchType.LAZY)
    @JoinTable(name = "requestforquote_organisationalUnitSupplier", joinColumns = {@JoinColumn(name = "requestforquote_id")},
            inverseJoinColumns = {@JoinColumn(name = "organisationalUnitSuppliers_id")})
    private List<OrganisationalUnitSupplier> organisationalUnitSuppliers=new ArrayList<>();

    public String getReference() {
        return reference;
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Date getLatestShippingDate() {
        return latestShippingDate;
    }

    public void setLatestShippingDate(Date latestShippingDate) {
        this.latestShippingDate = latestShippingDate;
    }

    public Date getRequiredClosureDate() {
        return requiredClosureDate;
    }

    public void setRequiredClosureDate(Date requiredClosureDate) {
        this.requiredClosureDate = requiredClosureDate;
    }

    public RequestForQuoteState getState() {
        return state;
    }

    public void setState(RequestForQuoteState state) {
        this.state = state;
    }

    public Date getCreationDate() {
        return creationDate;
    }

    public void setCreationDate(Date creationDate) {
        this.creationDate = creationDate;
    }

    public List<OrganisationalUnit> getOrganisationalUnits() {
        return organisationalUnits;
    }

    public void setOrganisationalUnits(List<OrganisationalUnit> organisationalUnits) {
        this.organisationalUnits = organisationalUnits;
    }

    public List<OrganisationalUnit> getOrganisationalUnits2() {
        if(organisationalUnits==null){
            organisationalUnits=new ArrayList<>();
        }
        return new ArrayList<>(organisationalUnits);
    }

    public void setOrganisationalUnits2(List<OrganisationalUnit> organisationalUnits) {
        this.organisationalUnits = organisationalUnits;
    }

    public RFQRule getRfqRule() {
        return rfqRule;
    }

    public void setRfqRule(RFQRule rfqRule) {
        this.rfqRule = rfqRule;
    }

    public List<RFQOrganisationalUnitSupplier> getRfqOrganisationalUnitSuppliers() {
        if (rfqOrganisationalUnitSuppliers == null) {
            rfqOrganisationalUnitSuppliers = new ArrayList<>();
        }
        return rfqOrganisationalUnitSuppliers;
    }

    public void setRfqOrganisationalUnitSuppliers(List<RFQOrganisationalUnitSupplier> rfqOrganisationalUnitSuppliers) {
        this.rfqOrganisationalUnitSuppliers = rfqOrganisationalUnitSuppliers;
    }

    public Incoterm getIncoterm() {
        return incoterm;
    }

    public void setIncoterm(Incoterm incoterm) {
        this.incoterm = incoterm;
    }

    public Date getRequiredAtDestinationDate() {
        return requiredAtDestinationDate;
    }

    public void setRequiredAtDestinationDate(Date requiredAtDestinationDate) {
        this.requiredAtDestinationDate = requiredAtDestinationDate;
    }

    public List<RFQStyle> getRfqStyles() {
        return rfqStyles;
    }

    public void setRfqStyles(List<RFQStyle> rfqStyles) {
        this.rfqStyles = rfqStyles;
    }

    @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;
        RequestForQuote request = (RequestForQuote) o;
        return Objects.equals(reference, request.reference);
    }

    @Override
    public int hashCode() {
        return Objects.hash(super.hashCode(), reference);
    }

    @Override
    public RequestForQuoteEvent getLastEvent() {
        return Event.getLastEvent(events);
    }

    @Override
    public List<RequestForQuoteEvent> getEvents() {
        return events;
    }

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

    public final static Collection<RequestForQuoteState> EDITABLE_STATES
            = Arrays.asList(RequestForQuoteState.DRAFT, RequestForQuoteState.SENT_FOR_REVIEW,RequestForQuoteState.AWAITING_BRANCH_CONFIRMATION,
            RequestForQuoteState.BRANCH_CONFIRMED);

    @Override
    public boolean inNonEditableState() {
        return !EDITABLE_STATES.contains(state);
    }

    public boolean inEditableState() {
        return EDITABLE_STATES.contains(state);
    }

    public boolean managerNonEditableState() {
        return EDITABLE_STATES.contains(RequestForQuoteState.DRAFT);
    }

    public Date getStockLevelGenDate() {
        return stockLevelGenDate;
    }

    public void setStockLevelGenDate(Date stockLevelGenDate) {
        this.stockLevelGenDate = stockLevelGenDate;
    }

    public List<OrganisationalUnitSupplier> getOrganisationalUnitSuppliers() {
        return organisationalUnitSuppliers;
    }

    public void setOrganisationalUnitSuppliers(List<OrganisationalUnitSupplier> organisationalUnitSuppliers) {
        this.organisationalUnitSuppliers = organisationalUnitSuppliers;
    }

    public String getOrganisationalUnitNames(){
        return organisationalUnits.stream().map(OrganisationalUnit::getName).collect(Collectors.joining(","));
    }

    public boolean isApprovedByAllManagers() {
        return approvedByAllManagers;
    }

    public void setApprovedByAllManagers(boolean approvedByAllManagers) {
        this.approvedByAllManagers = approvedByAllManagers;
    }

    public Date getBranchSubmissionDate() {
        return branchSubmissionDate;
    }

    public void setBranchSubmissionDate(Date branchSubmissionDate) {
        this.branchSubmissionDate = branchSubmissionDate;
    }

    public boolean isAwaitingBranchManager(){
        return state==RequestForQuoteState.AWAITING_BRANCH_CONFIRMATION ;
    }

    public List<RFQOrder> getRfqOrders() {
        return rfqOrders;
    }

    public void setRfqOrders(List<RFQOrder> rfqOrders) {
        this.rfqOrders = rfqOrders;
    }

    public void addRfqStyle(RFQStyle rfqStyle) {
        rfqStyle.setRequestForQuote(this);
        this.rfqStyles.add(rfqStyle);
    }

    public void addRfqOrganisationalUnitSupplier(RFQOrganisationalUnitSupplier supplier) {
        supplier.setRequestForQuote(this);
        getRfqOrganisationalUnitSuppliers().add(supplier);
    }

    public boolean isConsolidationViewable() {
        return state == RequestForQuoteState.CLOSED ||
               state == RequestForQuoteState.AWAITING_APPROVAL ||
               state == RequestForQuoteState.AWARDED;
    }

    public boolean isNotSavedChanges() {
        return notSavedChanges;
    }

    public void setNotSavedChanges(boolean notSavedChanges) {
        this.notSavedChanges = notSavedChanges;
    }
}