Product.java
package com.tradecloud.domain.item;
import com.tradecloud.domain.CommissionInformation;
import com.tradecloud.domain.base.utils.MathUtils;
import com.tradecloud.domain.common.ProductProperty;
import com.tradecloud.domain.costing.ElcDimensions;
import com.tradecloud.domain.dms.DocumentManagementHardCoding;
import com.tradecloud.domain.duties.*;
import com.tradecloud.domain.event.Event;
import com.tradecloud.domain.event.ProductStateHistory;
import com.tradecloud.domain.model.DMSLinked;
import com.tradecloud.domain.model.hfcmanagement.ProductGroup;
import com.tradecloud.domain.model.ordermanagement.ProductState;
import com.tradecloud.domain.model.organisationalunit.OrganisationalUnit;
import com.tradecloud.domain.place.Country;
import com.tradecloud.domain.state.Stateful;
import com.tradecloud.domain.supplier.OrganisationalUnitSupplier;
import org.apache.commons.lang3.StringUtils;
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.math.BigDecimal;
import java.util.*;
@Entity
@Table(name = "product", uniqueConstraints = {@UniqueConstraint(columnNames = {"code", "supplier_id", "countryoforigin_code",
"organisationalunit_id"})})
@Access(AccessType.FIELD)
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "Product")
public class Product extends AbstractItem implements Comparable<Product>, ElcDimensions, Stateful<ProductState,
ProductStateHistory>, ItemInterface, DMSLinked {
private static final long serialVersionUID = 1L;
public Product(String code, OrganisationalUnitSupplier supplier, OrganisationalUnit organisationalUnit, Country countryOfOrigin) {
this.setCode(code);
this.setOrganisationalUnit(organisationalUnit);
this.setSupplier(supplier);
this.setCountryOfOrigin(countryOfOrigin);
}
public enum Type {
FULL, TEMPLATE, ELC, PRE_PACK
}
@ManyToOne
@JoinColumn(name = "unittype_code")
@ForeignKey(name = "fk_unittype")
@XmlElement(name = "UnitType")
@NotNull(message = "Unit Type is a required field")
protected UnitType unitType;
@ManyToOne
@JoinColumn(name = "packagetype_code")
@ForeignKey(name = "fk_packagetype")
@XmlElement(name = "PackageType")
protected PackageType packageType;
@ManyToOne
@XmlElement(name = "ProductCategory")
private ProductCategory productCategory;
@ManyToOne
@XmlElement(name = "ProductsubCategory")
private ProductSubCategory productSubCategory;
@ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.REMOVE)
@XmlTransient
private ProductGroup productGroup;
/**
* Bit of hassle with Postgres and the @Lob annotation so this is the
* recommended approach for now. TODO - untested as yet.
*/
@Basic(fetch = FetchType.LAZY)
@org.hibernate.annotations.Type(type = "org.hibernate.type.BinaryType")
private byte[] image;
@XmlAttribute
protected String tariffDescription;
@XmlAttribute
protected String lastLandedCostCurrencyCode;
@XmlAttribute
protected BigDecimal unitQuantityAvailable;
@XmlAttribute
protected BigDecimal sabsPercentage;
@XmlAttribute
protected BigDecimal royaltyPercentage;
@XmlAttribute
protected BigDecimal exciseDutyPercentage;
@Transient
@XmlAttribute
private BigDecimal customsDuty;
@Transient
@XmlAttribute
private String tariffed;
@Transient
@XmlAttribute
private String tariffHeading;
@Transient
@XmlAttribute
private String additionalTariff;
/**
* Product statuses.
*/
@Enumerated(EnumType.STRING)
@XmlAttribute(name = "State")
private ProductState state = ProductState.UNTARIFFED;
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@Fetch(value = FetchMode.SELECT)
@XmlElementWrapper(name = "ProductEvent")
@XmlElement(name = "ProductEvent")
@OrderBy("createDateTime")
@JoinTable(name = "product_productstatehistory",
joinColumns = @JoinColumn(name = "product_id"),
inverseJoinColumns = @JoinColumn(name = "productstatehistory_id"))
private List<ProductStateHistory> events = new LinkedList<ProductStateHistory>();
/**
* Indicates if order was created via integration interface.
*/
@XmlAttribute
protected boolean integrated;
@XmlAttribute
private boolean portHealthInspectionFee;
@XmlAttribute
private BigDecimal sellPriceExclusiveAmount;
@XmlAttribute
private BigDecimal sellPriceInclusiveAmount;
@XmlAttribute
private String materialComposition;
@XmlAttribute
private BigDecimal lastLandedCostAmount;
@Embedded
@XmlElement(name = "CommissionInformation")
private CommissionInformation commissionInformation = new CommissionInformation();
@XmlAttribute
private BigDecimal sellingPrice;
//todo product cannot be both export and import, we need just one boolean field(importProduct or exportProduct)
@XmlAttribute
protected boolean importProduct;
@XmlAttribute
protected boolean exportProduct;
private boolean complete;
@XmlTransient
@Enumerated(EnumType.STRING)
private Type type = Type.FULL;
@ElementCollection(fetch = FetchType.EAGER, targetClass = ProductProperty.class)
@Enumerated(EnumType.STRING)
@CollectionTable(name = "productproperties")
@Column(name = "product_property")
@Fetch(value = FetchMode.SELECT)
protected Set<ProductProperty> productProperties = new HashSet<>();
@XmlElementWrapper(name = "additionalNotes")
@XmlElement(name = "ProductNote")
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true)
@Fetch(value = FetchMode.SELECT)
@JoinTable(name = "product_productnotes", joinColumns = @JoinColumn(name = "product_id"),
inverseJoinColumns = @JoinColumn(name = "product_notes_id"))
private List<AdditionalNotes> additionalNotes = new ArrayList<>();
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@Fetch(value = FetchMode.SELECT)
@CollectionTable(name = "product_producthistory")
@Column(name = "product_id")
@JoinTable(name = "product_producthistory", joinColumns = @JoinColumn(name = "product_id"),
inverseJoinColumns = @JoinColumn(name = "history_id"))
private List<ProductHistory> history = new LinkedList<ProductHistory>();
// @ManyToOne(fetch = FetchType.LAZY)
// @JoinFormula("(SELECT MAX(product_producthistory.history_id) " +
// "FROM product_producthistory left join producthistory on product_producthistory.history_id = producthistory.id " +
// "WHERE product_producthistory.product_id = id and producthistory.type = 'LAST_GRN' AND producthistory.type = 'LAST_LC')")
// private ProductHistory lastLandedCostGRN;
@Transient
private boolean elc;
@Transient
private String supplierName;
private String templateDescription;
private boolean sadcCertificateAdded;
@OneToOne(cascade = CascadeType.ALL)
private Homologation homologation;
private boolean useForRfq;
public boolean isImportProduct() {
return importProduct;
}
public void setImportProduct(boolean importProduct) {
this.importProduct = importProduct;
}
public boolean isExportProduct() {
return exportProduct;
}
public void setExportProduct(boolean exportProduct) {
this.exportProduct = exportProduct;
}
public BigDecimal getSellingPrice() {
return sellingPrice;
}
public void setSellingPrice(BigDecimal sellingPrice) {
this.sellingPrice = sellingPrice;
}
public ProductCategory getProductCategory() {
return productCategory;
}
public void setProductCategory(ProductCategory productCategory) {
this.productCategory = productCategory;
}
public ProductSubCategory getProductSubCategory() {
return productSubCategory;
}
public void setProductSubCategory(ProductSubCategory productSubCategory) {
this.productSubCategory = productSubCategory;
}
public Product() {
}
public String getLastLandedCostCurrencyCode() {
return lastLandedCostCurrencyCode;
}
public void setLastLandedCostCurrencyCode(String lastLandedCostCurrencyCode) {
this.lastLandedCostCurrencyCode = lastLandedCostCurrencyCode;
}
public BigDecimal getUnitQuantityAvailable() {
return unitQuantityAvailable;
}
public void setUnitQuantityAvailable(BigDecimal unitQuantityAvailable) {
this.unitQuantityAvailable = unitQuantityAvailable;
}
public String getTariffDescription() {
return tariffDescription;
}
public void setTariffDescription(String tariffDescription) {
this.tariffDescription = tariffDescription;
}
public byte[] getImage() {
return image;
}
public void setImage(byte[] image) {
this.image = image;
}
public String getSupplierReference() {
return supplierReference;
}
public void setSupplierReference(String supplierReference) {
this.supplierReference = supplierReference;
}
public UnitType getUnitType() {
return unitType;
}
public void setUnitType(UnitType unitType) {
this.unitType = unitType;
}
public PackageType getPackageType() {
return packageType;
}
@Override
public boolean applyItacPermit() {
return ItemProductUtil.isValidRebateSchedule4(this) || ItemProductUtil.isValidRebateSchedule3(this);
}
public void setPackageType(PackageType packageType) {
this.packageType = packageType;
}
@Override
public String toString() {
return this.getDescription() + " [id: " + getId() + ", reference: " + getCode() + "]";
}
public String getStyleReference() {
return styleReference;
}
public void setStyleReference(String styleReference) {
this.styleReference = styleReference;
}
public String getStyleDescription() {
return styleDescription;
}
public void setStyleDescription(String styleDescription) {
this.styleDescription = styleDescription;
}
public ProductGroup getProductGroup() {
return productGroup;
}
public void setProductGroup(ProductGroup productGroup) {
this.productGroup = productGroup;
}
public String getTariffed() {
TariffHeading tariffHeading = this.getSchedule1Part1A() != null ? this.getSchedule1Part1A().getTariffHeading() : null;
if (tariffHeading != null && StringUtils.isNoneEmpty(tariffHeading.getTariff()) && this.getSchedule1Part1A().isValid()) {
tariffed = "Yes";
} else {
tariffed = "No";
}
return tariffed;
}
public void setDutyPercentage(BigDecimal customsDuty) {
this.customsDuty = customsDuty;
}
public BigDecimal getDutyPercentage() {
if (getSchedule1Part1A() != null && getSchedule1Part1A().getDutyRate() != null) {
customsDuty = getSchedule1Part1A().getDutyRate().getPercentage();
}
return customsDuty;
}
public void setTariffed(String tariffed) {
this.tariffed = tariffed;
}
public String getTariffHeading() {
TariffHeading tHeading = this.getSchedule1Part1A() != null ? this.getSchedule1Part1A().getTariffHeading() : null;
if (tHeading != null)
tariffHeading = tHeading.getTariffHeading();
return tariffHeading;
}
public void setTariffHeading(String tHeading) {
this.tariffHeading = tHeading;
}
public String getAdditionalTariff() {
TariffHeading heading1_2A = this.getSchedule1Part2A() != null ? this.getSchedule1Part2A().getTariffHeading() : null;
TariffHeading heading1_2B = this.getSchedule1Part2B() != null ? this.getSchedule1Part2B().getTariffHeading() : null;
TariffHeading heading1_3E = this.getSchedule1Part3E() != null ? this.getSchedule1Part3E().getTariffHeading() : null;
TariffHeading heading2_1 = this.getSchedule2Part1() != null ? this.getSchedule2Part1().getTariffHeading() : null;
TariffHeading heading2_2 = this.getSchedule2Part2() != null ? this.getSchedule2Part2().getTariffHeading() : null;
if (heading1_2A != null && StringUtils.isNoneEmpty(heading1_2A.getTariff()) && this.getSchedule1Part2A().isValid()) {
additionalTariff = "Yes";
} else if (heading1_2B != null && StringUtils.isNoneEmpty(heading1_2B.getTariff()) && this.getSchedule1Part2B().isValid()) {
additionalTariff = "Yes";
} else if (heading1_3E != null && StringUtils.isNoneEmpty(heading1_3E.getTariff()) && this.getSchedule1Part3E().isValid()) {
additionalTariff = "Yes";
} else if (heading2_1 != null && StringUtils.isNoneEmpty(heading2_1.getTariff()) && this.getSchedule2Part1().isValid()) {
additionalTariff = "Yes";
} else if (heading2_2 != null && StringUtils.isNoneEmpty(heading2_2.getTariff()) && this.getSchedule2Part2().isValid()) {
additionalTariff = "Yes";
} else {
additionalTariff = "No";
}
return additionalTariff;
}
public void setAdditionalTariff(String additionalTariff) {
this.additionalTariff = additionalTariff;
}
@Override
public int compareTo(Product o) {
if (created != null && o.created != null) {
return o.created.compareTo(created);
}
return 0;
}
public void init() {
if (getSchedule1Part2A() == null) {
setSchedule1Part2A(new Schedule1Part2A());
getSchedule1Part2A().setDutyRate(new DutyRate());
getSchedule1Part2A().getDutyRate().setValue(BigDecimal.ZERO);
}
if (getSchedule1Part2B() == null) {
setSchedule1Part2B(new Schedule1Part2B());
getSchedule1Part2B().setDutyRate(new TypedDutyRate());
getSchedule1Part2B().getDutyRate().setValue(BigDecimal.ZERO);
}
if (getSchedule2Part1() == null) {
setSchedule2Part1(new Schedule2Part1());
getSchedule2Part1().setDutyRate(new TypedDutyRate());
getSchedule2Part1().getDutyRate().setValue(BigDecimal.ZERO);
}
if (getSchedule1Part1A() == null) {
setSchedule1Part1A(new Schedule1Part1A());
getSchedule1Part1A().setDutyRate(new TypedDutyRate());
getSchedule1Part1A().getDutyRate().setValue(BigDecimal.ZERO);
}
if (getSchedule2Part2() == null) {
setSchedule2Part2(new Schedule2Part2());
getSchedule2Part2().setDutyRate(new TypedDutyRate());
getSchedule2Part2().getDutyRate().setValue(BigDecimal.ZERO);
}
if (getSchedule1Part3E() == null) {
setSchedule1Part3E(new Schedule1Part3E());
getSchedule1Part3E().setDutyRate(new TypedDutyRate());
getSchedule1Part3E().getDutyRate().setValue(BigDecimal.ZERO);
}
if (getSchedule1Part7() == null) {
setSchedule1Part7(new Schedule1Part7());
getSchedule1Part7().setDutyRate(new TypedDutyRate());
getSchedule1Part7().getDutyRate().setValue(BigDecimal.ZERO);
}
if (getSchedule3Part1() == null) {
setSchedule3Part1(new Schedule3Part1());
getSchedule3Part1().setDutyRate(new TypedDutyRate());
getSchedule3Part1().getDutyRate().setValue(BigDecimal.ZERO);
}
if (getSchedule4Part1() == null) {
setSchedule4Part1(new Schedule4Part1());
getSchedule4Part1().setDutyRate(new TypedDutyRate());
getSchedule4Part1().getDutyRate().setValue(BigDecimal.ZERO);
}
}
public boolean isIntegrated() {
return integrated;
}
public void setIntegrated(boolean integrated) {
this.integrated = integrated;
}
public boolean isPortHealthInspectionFee() {
return portHealthInspectionFee;
}
public void setPortHealthInspectionFee(boolean portHealthInspectionFee) {
this.portHealthInspectionFee = portHealthInspectionFee;
}
public CommissionInformation getCommissionInformation() {
if (commissionInformation == null) {
commissionInformation = new CommissionInformation();
}
return commissionInformation;
}
public void setCommissionInformation(CommissionInformation commissionInformation) {
this.commissionInformation = commissionInformation;
}
public BigDecimal getSabsPercentage() {
return sabsPercentage;
}
public void setSabsPercentage(BigDecimal sabsPercentage) {
this.sabsPercentage = sabsPercentage;
}
public BigDecimal getRoyaltyPercentage() {
return royaltyPercentage;
}
public void setRoyaltyPercentage(BigDecimal royaltyPercentage) {
this.royaltyPercentage = royaltyPercentage;
}
public BigDecimal getExciseDutyPercentage() {
return exciseDutyPercentage;
}
public void setExciseDutyPercentage(BigDecimal exciseDutyPercentage) {
this.exciseDutyPercentage = exciseDutyPercentage;
}
public BigDecimal getSellPriceExclusiveAmount() {
return sellPriceExclusiveAmount;
}
public void setSellPriceExclusiveAmount(BigDecimal sellPriceExclusiveAmount) {
this.sellPriceExclusiveAmount = sellPriceExclusiveAmount;
}
public BigDecimal getSellPriceInclusiveAmount() {
return sellPriceInclusiveAmount;
}
public void setSellPriceInclusiveAmount(BigDecimal sellPriceInclusiveAmount) {
this.sellPriceInclusiveAmount = sellPriceInclusiveAmount;
}
public String getMaterialComposition() {
return materialComposition;
}
public void setMaterialComposition(String materialComposition) {
this.materialComposition = materialComposition;
}
public BigDecimal getLastLandedCostAmount() {
return lastLandedCostAmount;
}
public void setLastLandedCostAmount(BigDecimal lastLandedCostAmount) {
//it is not mandatory but it cannot be cleared once set.
if (lastLandedCostAmount != null) {
this.lastLandedCostAmount = lastLandedCostAmount;
}
}
public boolean isComplete() {
return complete;
}
public void setComplete(boolean complete) {
this.complete = complete;
}
@Override
public BigDecimal getPackageVolume() {
if (packageVolume != null && !MathUtils.isZero(packageVolume)) {
return packageVolume;
}
ItemProductUtil.calculateAndSetVolume(this, packageVolume, unitVolume);
return packageVolume;
}
@Override
public Date getAddedToOrderDate() {
return null;
}
public ProductState getState() {
return state;
}
public void setState(ProductState state) {
this.state = state;
}
@Override
public ProductStateHistory getLastEvent() {
return Event.getLastEvent(events);
}
@Override
public List<ProductStateHistory> getEvents() {
return events;
}
@Override
public boolean inNonEditableState() {
return false;
}
public static long getSerialVersionUID() {
return serialVersionUID;
}
public void setEvents(List<ProductStateHistory> events) {
this.events = events;
}
public List<AdditionalNotes> getAdditionalNotes() {
return additionalNotes;
}
public void setAdditionalNotes(List<AdditionalNotes> additionalNotes) {
this.additionalNotes = additionalNotes;
}
public Set<ProductProperty> getProductProperties() {
if (productProperties == null)
productProperties = new HashSet<>();
return productProperties;
}
public void setProductProperties(Set<ProductProperty> productProperties) {
this.productProperties = productProperties;
}
@Override
public BigDecimal getUnitQuantity() {
return unitQuantityAvailable;
}
@Override
public void setUnitQuantity(BigDecimal unitQuantity) {
unitQuantityAvailable = unitQuantity;
}
public Type getType() {
if (type == null) {
type = Type.FULL;
}
return type;
}
public void setType(Type type) {
this.type = type;
}
public BigDecimal getCustomsDuty() {
return customsDuty;
}
public void setCustomsDuty(BigDecimal customsDuty) {
this.customsDuty = customsDuty;
}
public List<ProductHistory> getHistory() {
return history;
}
public void setHistory(List<ProductHistory> history) {
this.history = history;
}
// public ProductHistory getLastLandedCostGRN() {
// return lastLandedCostGRN;
// }
public Type getElcOrFull() {
if (this.type == Type.ELC) {
return this.type;
}
return Type.FULL;
}
public boolean isElc() {
return elc;
}
public void setElc(boolean elc) {
this.elc = elc;
}
public String getSupplierName() {
return supplierName;
}
public void setSupplierName(String supplierName) {
this.supplierName = supplierName;
}
public String getTemplateDescription() {
return templateDescription;
}
public void setTemplateDescription(String templateDescription) {
this.templateDescription = templateDescription;
}
@Override
public Set<ProductProperty> getProperties() {
return getProductProperties();
}
public boolean isSadcCertificateAdded() {
return sadcCertificateAdded;
}
public void setSadcCertificateAdded(boolean sadcCertificateAdded) {
this.sadcCertificateAdded = sadcCertificateAdded;
}
@Override
public BigDecimal getPenaltyAmount() {
return null;
}
@Override
public void setPenaltyAmount(BigDecimal penaltyAmount) {
}
@Override
public boolean inTariffiedState() {
return state == ProductState.TARIFFED.TARIFFED;
}
@Override
public String getDMSKey() {
if (getSupplier() != null) {
return new StringBuilder()
.append(getCode())
.append(getCountryOfOrigin().getCode())
.append(getSupplier().getSupplier().getCode())
.append(getOrganisationalUnit().getCode())
.toString();
} else {
return new StringBuilder()
.append(getCode())
.append(getCountryOfOrigin().getCode())
.append(getOrganisationalUnit().getCode())
.toString();
}
}
@Override
public String getDocumentGroupName() {
return DocumentManagementHardCoding.PRODUCT.name();
}
@Override
public String getReference() {
return getCode();
}
@Override
public String getImplementationType() {
return "PRODUCT";
}
public Homologation getHomologation() {
return homologation;
}
public void setHomologation(Homologation homologation) {
this.homologation = homologation;
}
public boolean isUseForRfq() {
return useForRfq;
}
public void setUseForRfq(boolean useForRfq) {
this.useForRfq = useForRfq;
}
}