ServiceProvider.java

package com.tradecloud.domain.party;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.tradecloud.common.base.HibernateUtils;
import com.tradecloud.domain.clearing.CustomsAccount;
import com.tradecloud.domain.configuration.clearing.za.SARSImportConfig;
import com.tradecloud.domain.configuration.orderintegration.ServiceProviderOrderIntegrationProperties;
import com.tradecloud.domain.configuration.shipment.ShipmentAndContainerValidationConfig;
import com.tradecloud.domain.configuration.shipment.ShipmentIntegrationProperties;
import com.tradecloud.domain.model.Customs;
import com.tradecloud.domain.model.organisationalunit.Logo;
import com.tradecloud.domain.model.organisationalunit.LogoHolder;
import com.tradecloud.domain.model.payment.ActualPaymentBasis;
import com.tradecloud.domain.model.payment.EstimatedPaymentBasis;
import com.tradecloud.domain.model.payment.PaymentMethod;
import com.tradecloud.domain.model.payment.PaymentTerm;
import com.tradecloud.domain.party.base.Company;
import com.tradecloud.domain.supplier.Creditor;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;
import org.hibernate.annotations.ForeignKey;

import javax.persistence.*;
import javax.validation.constraints.NotNull;
import javax.xml.bind.annotation.*;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * ServiceProvider.
 */
@Entity
@Access(AccessType.FIELD)
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "ServiceProvider")
@Table(name = "serviceprovider", uniqueConstraints = {@UniqueConstraint(columnNames = {"name"})})
public class ServiceProvider extends Company implements Comparable<ServiceProvider>, Creditor, LogoHolder, Customs {

    private boolean produceExportManifest;
    private String customsCode;
    private String carrierCode;
    private String cargoCarrierCode;
    private String customsFinancialAccountNumber;

    private boolean autoGenerateInvoice;

    private boolean costCompareOnly;
    @ManyToOne(fetch = FetchType.LAZY)
    private SARSImportConfig sarsImportConfig;
    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private List<CustomsAccount> customsAccounts;

    private boolean requireInvoiceLineNoOnSignOff;
    @Enumerated
    private InvoiceLineDescriptionDefault lineDescriptionDefault;


    public ServiceProvider() {
        integrated = Boolean.FALSE;
    }

    public ServiceProvider(String name) {
        super(name);
        integrated = Boolean.FALSE;
    }

    public ServiceProvider(Set<ServiceProviderType> serviceProviderTypes, PaymentTerm paymentTerm, PaymentMethod paymentMethod,
                           EstimatedPaymentBasis estimatedPaymentBasis, ActualPaymentBasis actualPaymentBasis, Boolean integrated) {
        super();
        this.serviceProviderTypes = serviceProviderTypes;
        this.paymentTerm = paymentTerm;
        this.paymentMethod = paymentMethod;
        this.estimatedPaymentBasis = estimatedPaymentBasis;
        this.actualPaymentBasis = actualPaymentBasis;
        this.integrated = integrated;
    }

    private static final long serialVersionUID = 1L;

    @ElementCollection(fetch = FetchType.EAGER)
    @Column(name = "serviceprovidertype")
    @Fetch(FetchMode.SELECT)
    @Enumerated(EnumType.STRING)
    @ForeignKey(name = "fk_serviceprovider", inverseName = "fk_serviceprovidertype")
    private Set<ServiceProviderType> serviceProviderTypes = new HashSet<>();

    //we do not need bi direction (slow performance when loading shipment)
//    @XmlTransient
//    @JsonIgnore
//    @ManyToOne(fetch = FetchType.LAZY)
//    @JoinTable(name = "shipmentclientconfig_serviceprovider", joinColumns = {@JoinColumn(name = "serviceprovider_id")},
//            inverseJoinColumns = {@JoinColumn(name = "shipmentclientconfig_id")})
//    private ShipmentClientConfig shipmentClientConfig;

    @XmlTransient
    @JsonIgnore
    @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    @JoinTable(name = "serviceprovider_shipmentintegrationproperties", joinColumns = {@JoinColumn(name = "serviceprovider_id")},
            inverseJoinColumns = {@JoinColumn(name = "shipmentintegrationproperties_id")})
    private ShipmentIntegrationProperties shipmentIntegrationProperties;

    @XmlTransient
    @JsonIgnore
    @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    @JoinTable(name = "serviceprovider_serviceProviderOrderIntegrationProperties", joinColumns = {@JoinColumn(name = "serviceprovider_id")},
            inverseJoinColumns = {@JoinColumn(name = "serviceProviderOrderIntegrationProperties_id")})
    private ServiceProviderOrderIntegrationProperties serviceProviderOrderIntegrationProperties;

    @XmlTransient
    @JsonIgnore
    @OneToOne(cascade = CascadeType.ALL)
    private ShipmentAndContainerValidationConfig shipmentAndContainerValidationConfig;


    @ManyToOne
    @XmlElement(name = "PaymentTerm")
    private PaymentTerm paymentTerm;

    @ManyToOne
    @XmlElement(name = "PaymentMethod")
    private PaymentMethod paymentMethod;

    @ManyToOne
    @NotNull(message = "Estimated payment basis is required")
    @XmlElement(name = "EstimatedPaymentBasis", required = true)
    private EstimatedPaymentBasis estimatedPaymentBasis;

    @ManyToOne
    @NotNull(message = "Actual payment basis is required")
    @XmlElement(name = "ActualPaymentBasis", required = true)
    private ActualPaymentBasis actualPaymentBasis;

    /**
     * Whether or not tradecloud is integrated to this service provider.
     */
    private Boolean integrated;
    private String url;

    @XmlTransient
    @JsonIgnore
    @OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true)
    private Logo logoImage;

    public PaymentTerm getPaymentTerm() {
        return paymentTerm;
    }

    public void setPaymentTerm(PaymentTerm paymentTerm) {
        this.paymentTerm = paymentTerm;
    }

    public PaymentMethod getPaymentMethod() {
        return paymentMethod;
    }

    public void setPaymentMethod(PaymentMethod paymentMethod) {
        this.paymentMethod = paymentMethod;
    }

    public ActualPaymentBasis getActualPaymentBasis() {
        return actualPaymentBasis;
    }

    public void setActualPaymentBasis(ActualPaymentBasis actualPaymentBasis) {
        this.actualPaymentBasis = actualPaymentBasis;
    }

    public EstimatedPaymentBasis getEstimatedPaymentBasis() {
        return estimatedPaymentBasis;
    }

    public void setEstimatedPaymentBasis(EstimatedPaymentBasis estimatedPaymentBasis) {
        this.estimatedPaymentBasis = estimatedPaymentBasis;
    }

    public Boolean getIntegrated() {
        return integrated;
    }

    public void setIntegrated(Boolean integrated) {
        this.integrated = integrated;
    }

    /**
     * TODO - just using values from the parent for now.
     */
    @Override
    public int compareTo(ServiceProvider serviceProvider) {
        if (getName() != null) {
            if (getName().compareTo(serviceProvider.getName()) != 0) {
                return getName().compareTo(serviceProvider.getName());
            }
        }
        if (getExternalReference() != null) {
            if (getExternalReference().compareTo(serviceProvider.getExternalReference()) != 0) {
                return getExternalReference().compareTo(serviceProvider.getExternalReference());
            }
        }

        if (getSalesTaxRegistrationNumber() != null) {
            if (getSalesTaxRegistrationNumber().compareTo(serviceProvider.getSalesTaxRegistrationNumber()) != 0) {
                return getSalesTaxRegistrationNumber().compareTo(serviceProvider.getSalesTaxRegistrationNumber());
            }
        }

        if (getVatRegistrationNumber() != null) {
            if (getVatRegistrationNumber().compareTo(serviceProvider.getVatRegistrationNumber()) != 0) {
                return getVatRegistrationNumber().compareTo(serviceProvider.getVatRegistrationNumber());
            }
        }

        if (getCompanyRegistrationNumber() != null) {
            if (getCompanyRegistrationNumber().compareTo(serviceProvider.getCompanyRegistrationNumber()) != 0) {
                return getCompanyRegistrationNumber().compareTo(serviceProvider.getCompanyRegistrationNumber());
            }
        }

        if (getWarehouseCode() != null) {
            if (getWarehouseCode().compareTo(serviceProvider.getWarehouseCode()) != 0) {
                return getWarehouseCode().compareTo(serviceProvider.getWarehouseCode());
            }
        }

        return 0;
    }

    public Set<ServiceProviderType> getServiceProviderTypes() {
        return serviceProviderTypes;
    }

    public void setServiceProviderTypes(Set<ServiceProviderType> serviceProviderTypes) {
        this.serviceProviderTypes = serviceProviderTypes;
    }

    public ShipmentIntegrationProperties getShipmentIntegrationProperties() {
        return shipmentIntegrationProperties;
    }

    public void setShipmentIntegrationProperties(ShipmentIntegrationProperties shipmentIntegrationProperties) {
        this.shipmentIntegrationProperties = shipmentIntegrationProperties;
    }

    @Override
    public String toString() {
        return new ToStringBuilder(super.toString()).append("name", getName())
                .append("paymentTerm", paymentTerm).append("paymentMethod", paymentMethod)
                .append("estimatedPaymentBasis", estimatedPaymentBasis).append("actualPaymentBasis", actualPaymentBasis)
                .append("serviceProviderTypes", serviceProviderTypes).append("integrated", integrated).toString();
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (!HibernateUtils.proxyClassEquals(this, obj)) {
            return false;
        }
        ServiceProvider other = (ServiceProvider) obj;
        return new EqualsBuilder().appendSuper(super.equals(obj)).append(paymentTerm, other.getPaymentTerm())
                .append(paymentMethod, other.getPaymentMethod()).append(estimatedPaymentBasis, other.getEstimatedPaymentBasis())
                .append(actualPaymentBasis, other.getActualPaymentBasis()).append(integrated, other.getIntegrated()).isEquals();
    }

    @Override
    public int hashCode() {
        return new HashCodeBuilder().appendSuper(super.hashCode()).append(paymentTerm).append(paymentMethod)
                .append(estimatedPaymentBasis).append(actualPaymentBasis).append(integrated).toHashCode();
    }

    public ServiceProviderOrderIntegrationProperties getServiceProviderOrderIntegrationProperties() {
        return serviceProviderOrderIntegrationProperties;
    }

    public void setServiceProviderOrderIntegrationProperties(ServiceProviderOrderIntegrationProperties serviceProviderOrderIntegrationProperties) {
        this.serviceProviderOrderIntegrationProperties = serviceProviderOrderIntegrationProperties;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public boolean isProduceExportManifest() {
        return produceExportManifest;
    }

    public void setProduceExportManifest(boolean produceExportManifest) {
        this.produceExportManifest = produceExportManifest;
    }

    public Logo getLogoImage() {
        return logoImage;
    }

    public void setLogoImage(Logo logoImage) {
        this.logoImage = logoImage;
    }

    @Override
    public ServiceProvider initialize() {
        ServiceProvider initialize = (ServiceProvider) super.initialize();
        HibernateUtils.initializeAndUnproxy(initialize.getPhysicalAddress());
        HibernateUtils.initializeAndUnproxy(initialize.getPostalAddress());
        //Causes connection leak, if lazyloading happens on get contacts find other solution
        //HibernateUtils.initializeAndUnproxy(initialize.getContacts());
        HibernateUtils.initializeAndUnproxy(initialize.getSwiftCompliantAddress());
        //causes connectionissue
        //HibernateUtils.initializeAndUnproxy(initialize.getShipmentClientConfig());
        //HibernateUtils.initializeAndUnproxy(initialize.getShipmentIntegrationProperties());
        //HibernateUtils.initializeAndUnproxy(initialize.getServiceProviderOrderIntegrationProperties());
        return this;
    }

    public byte[] getImage() {
        if (logoImage != null) {
            return logoImage.getImage();
        }
        return null;
    }

    public void setImage(byte[] image) {
        if (logoImage != null) {
            this.logoImage.setImage(image);
        } else {
            logoImage = new Logo(image);
        }
    }

    public String getCustomsCode() {
        return customsCode;
    }

    public void setCustomsCode(String customsCode) {
        this.customsCode = customsCode;
    }

    public String getCarrierCode() {
        return carrierCode;
    }

    public void setCarrierCode(String carrierCode) {
        this.carrierCode = carrierCode;
    }

    public String getCustomsFinancialAccountNumber() {
        return customsFinancialAccountNumber;
    }

    public void setCustomsFinancialAccountNumber(String customsFinancialAccountNumber) {
        this.customsFinancialAccountNumber = customsFinancialAccountNumber;
    }

    public boolean isAutoGenerateInvoice() {
        return autoGenerateInvoice;
    }

    public void setAutoGenerateInvoice(boolean autoGenerateInvoice) {
        this.autoGenerateInvoice = autoGenerateInvoice;
    }

    public SARSImportConfig getSarsImportConfig() {
        return sarsImportConfig;
    }

    public void setSarsImportConfig(SARSImportConfig sarsImportConfig) {
        this.sarsImportConfig = sarsImportConfig;
    }

    public List<CustomsAccount> getCustomsAccounts() {
        return customsAccounts;
    }

    public void setCustomsAccounts(List<CustomsAccount> customsAccounts) {
        this.customsAccounts = customsAccounts;
    }

    public String getCargoCarrierCode() {
        return cargoCarrierCode;
    }

    public void setCargoCarrierCode(String cargoCarrierCode) {
        this.cargoCarrierCode = cargoCarrierCode;
    }

    public boolean isCostCompareOnly() {
        return costCompareOnly;
    }

    public void setCostCompareOnly(boolean costCompareOnly) {
        this.costCompareOnly = costCompareOnly;
    }

    public String getLogoFileName() {
        if (logoImage != null)
            return logoImage.getFileName();
        return null;
    }

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

    public ShipmentAndContainerValidationConfig getShipmentAndContainerValidationConfig() {
        return shipmentAndContainerValidationConfig;
    }

    public void setShipmentAndContainerValidationConfig(ShipmentAndContainerValidationConfig shipmentAndContainerValidationConfig) {
        this.shipmentAndContainerValidationConfig = shipmentAndContainerValidationConfig;
    }

    public boolean isRequireInvoiceLineNoOnSignOff() {
        return requireInvoiceLineNoOnSignOff;
    }

    public void setRequireInvoiceLineNoOnSignOff(boolean requireInvoiceLineNoOnSignOff) {
        this.requireInvoiceLineNoOnSignOff = requireInvoiceLineNoOnSignOff;
    }

    public InvoiceLineDescriptionDefault getLineDescriptionDefault() {
        return lineDescriptionDefault;
    }

    public void setLineDescriptionDefault(InvoiceLineDescriptionDefault lineDescriptionDefault) {
        this.lineDescriptionDefault = lineDescriptionDefault;
    }
}