LineItem.java
package com.tradecloud.domain.item;
import com.fasterxml.jackson.annotation.JsonBackReference;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.tradecloud.common.base.HibernateUtils;
import com.tradecloud.domain.CommissionInformation;
import com.tradecloud.domain.base.utils.MathUtils;
import com.tradecloud.domain.comment.AddedCommentIncCost;
import com.tradecloud.domain.comment.CommentType;
import com.tradecloud.domain.comment.Commentable;
import com.tradecloud.domain.common.HangerType;
import com.tradecloud.domain.common.ProductProperty;
import com.tradecloud.domain.costing.clean.CostingVisitor;
import com.tradecloud.domain.duties.DutySchedule;
import com.tradecloud.domain.event.Event;
import com.tradecloud.domain.event.LineItemEvent;
import com.tradecloud.domain.model.Original;
import com.tradecloud.domain.model.goodsreceivedreceipt.GoodsReceivedReceiptItem;
import com.tradecloud.domain.model.ordermanagement.Order;
import com.tradecloud.domain.model.ordermanagement.ProductState;
import com.tradecloud.domain.place.Country;
import com.tradecloud.domain.state.Stateful;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.commons.lang3.builder.CompareToBuilder;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;
import org.hibernate.annotations.ForeignKey;
import org.springframework.stereotype.Component;
import javax.persistence.*;
import javax.validation.constraints.NotNull;
import javax.xml.bind.annotation.*;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
@Inheritance(strategy = InheritanceType.JOINED)
@Entity
@Component(value = "lineitem")
@Table(name = "lineitem")
@Access(AccessType.FIELD)
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "LineItem")
@NamedQueries({
@NamedQuery(name = "lineItem.findOriginalByCodeAndOrderReference",
query = "from LineItem i where i.code = :code and i.order.orderReference = :orderReference " + "and i.copy is false"),
@NamedQuery(name = "lineItem.findCopyByCodeAndOrderReference",
query = "from LineItem i where i.code = :code and i.order.orderReference = :orderReference and i.copy is true"),
@NamedQuery(name = "lineItem.countFindCopyByCodeAndOrderReference",
query = "select count(i) from LineItem i where i.code = :code and i.order.orderReference = :orderReference"),
@NamedQuery(name = "lineItem.findLineItemBySupplierReferenceAndReference",
query = "from LineItem i where i.order = :order and i.supplierReference = :supplierReference and i.code = :code"),
@NamedQuery(name = "lineItem.findItemByCode", query = "from LineItem i where i.code = :code"),
@NamedQuery(name = "lineItem.findItemById", query = "from LineItem i where i.id = :id"),
@NamedQuery(name = "lineItem.findSampleAndSpareItems", query = "from LineItem i where i.order = :order and i.code in (:sample,:spare)"),
@NamedQuery(name = "lineItem.findItemsByOrder",
query = "select distinct i from LineItem i left join fetch i.events where i.order = :order order by i.created"),
@NamedQuery(name = "lineItem.findAdditionalItemsByOrder",
query = "from LineItem i where i.additional is true and i.order.consignment.shipment.id = :shipmentId"),
@NamedQuery(name = "lineItem.findItemByCodeAndOrderReferenceAndNumber",
query = "from LineItem i where i.code = :code and i.order.orderReference = :orderReference and i.order.number = :orderNumber"),
@NamedQuery(name = "lineItem.findNonCopiedByCodeAndSupplierReferenceAndOrderReference",
query = "from LineItem i where i.code = :code and i.supplierReference =:supplierReference and "
+ "i.order.orderReference = :orderReference and i.copy is false")})
public class LineItem extends AbstractItem implements Commentable<AddedCommentIncCost>, Original, Stateful<LineItemState, LineItemEvent>,
Comparable<LineItem>, AdditionalItem {
private static final long serialVersionUID = 1L;
/**
* Reference back to the owning Order parent.
*/
// NB: DO NOT WANT A CASCADE.ALL ADDED HERE, should not cascade delete up to
// the parent!
@ManyToOne(fetch = FetchType.LAZY)
@ForeignKey(name = "fk_order")
@NotNull(message = "Parent order should not be null")
@XmlAttribute(required = true)
@XmlIDREF
@JsonBackReference
private Order order;
/**
* LineItemState INITIALISED after object initialisation. (This is an
* internal state only).
*/
@Enumerated(EnumType.STRING)
@XmlAttribute(name = "State")
private LineItemState state = LineItemState.UNTARIFFED;
@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true)
@JoinColumn(name = "hangeritem_id")
private HangerLineItem hangerLineItem;
/**
* List of internal system events to track the history of an entity as it
* passes through the various defined states.
*/
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@Fetch(value = FetchMode.SUBSELECT)
@XmlElementWrapper(name = "LineItemEvents")
@XmlElement(name = "LineItemEvent")
@OrderBy("createDateTime")
private List<LineItemEvent> events = new LinkedList<LineItemEvent>();
@ManyToOne
@ForeignKey(name = "fk_unittype")
@NotNull(message = "Unit type should not be null")
@XmlElement(name = "UnitType", required = true)
protected UnitType unitType;
@ManyToOne
@ForeignKey(name = "fk_packagetype")
@NotNull(message = "Package type should not be null")
@XmlElement(name = "PackageType", required = true)
protected PackageType packageType;
@ElementCollection(fetch = FetchType.LAZY)
@CollectionTable(name = "lineitem_freetextcomments", joinColumns = {@JoinColumn(name = "lineitem_id", unique = false)})
@Column(name = "reason", unique = true)
@ForeignKey(name = "fk_lineitem")
@XmlElementWrapper(name = "FreeTextComments")
@XmlElement(name = "FreeTextComment")
@Fetch(value = FetchMode.SUBSELECT)
protected List<AddedCommentIncCost> comments = new ArrayList<AddedCommentIncCost>();
@XmlAttribute
@Temporal(TemporalType.TIMESTAMP)
protected Date createDate;
@XmlAttribute
protected String handlingDescription;
@XmlAttribute
protected String packingInstruction;
@XmlAttribute
protected String elcStyleDescription;
@NotNull(message = "Unit quantity should not be null")
@XmlAttribute(required = true)
protected BigDecimal unitQuantity;
@XmlAttribute
protected BigDecimal packageQuantity;
@XmlAttribute
protected BigDecimal roundedPackageQuantity;
@XmlAttribute
protected BigDecimal packagePrice;
@XmlAttribute
protected BigDecimal unitQuantityReceived;
@XmlAttribute
protected BigDecimal unitQuantityInvoiced;
@XmlAttribute
protected BigDecimal unitQuantityAvailable;
@XmlAttribute
protected BigDecimal unitQuantityReserved;
@XmlAttribute
protected BigDecimal unitQuantityToBePacked;
@XmlAttribute
protected BigDecimal unitQuantityPacked;
@XmlAttribute
protected boolean balanceClosed;
@XmlAttribute
protected BigDecimal unitSellingPrice;
@XmlAttribute
protected BigDecimal sabsPercentage;
@XmlAttribute
protected BigDecimal royaltyPercentage;
@XmlAttribute
protected BigDecimal exciseDutyPercentage;
@XmlAttribute
private BigDecimal lastLandedCostAmount;
@XmlAttribute
private BigDecimal sellingPrice;
@XmlAttribute
private BigDecimal dutyCharge;
@XmlAttribute
private BigDecimal exciseDuty;
@XmlAttribute
protected boolean freeOfCharge;
@XmlAttribute
private BigDecimal valueForCustom;
@Enumerated(EnumType.STRING)
@XmlAttribute(name = "ItemType")
private ItemType itemType = ItemType.GENERAL;
@Transient
private boolean fromApi;
@XmlAttribute
protected Integer lineNumber;
@XmlAttribute
@Enumerated(value = EnumType.STRING)
private HangerType hangerType;
@XmlAttribute
private Long parentLineItemId;
@Embedded
@XmlElement(name = "CommissionInformation")
private CommissionInformation commissionInformation = new CommissionInformation();
@OneToOne(mappedBy = "lineItem", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY)
@ForeignKey(name = "fk_lineitempromotion")
@XmlElement(name = "Promotion")
@JsonIgnore
private LineItemPromotion promotion = new LineItemPromotion();
@XmlAttribute
private boolean portHealthInspectionFee;
@Transient
private boolean isItemDutiesUpdated = false;
@XmlAttribute
@Temporal(TemporalType.TIMESTAMP)
protected Date requiredOnSiteDate;
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true)
@Fetch(value = FetchMode.SUBSELECT)
@JoinTable(name = "lineitem_AdditionalNotes", joinColumns = @JoinColumn(name = "lineitem_id"),
inverseJoinColumns = @JoinColumn(name = "notes_id"))
private Set<AdditionalNotes> additionalNotes = new HashSet<>();
@Enumerated(EnumType.STRING)
private AdditionalLineItemType freeStockType;
public enum Type {
FULL, ELC, CARTON_ITEM
}
//used for ordering item as per user ordering
@XmlAttribute
protected Integer position;
@Enumerated(value = EnumType.STRING)
private HomologationStatus homologationStatus;
public BigDecimal getValueForCustom() {
return valueForCustom;
}
@Override
public CommentType getCommentType() {
return CommentType.ITEM;
}
public void setValueForCustom(BigDecimal valueForCustom) {
this.valueForCustom = valueForCustom;
}
public boolean isFreeOfCharge() {
return freeOfCharge;
}
public void setFreeOfCharge(boolean freeOfCharge) {
this.freeOfCharge = freeOfCharge;
}
public Date getRequiredOnSiteDate() {
return requiredOnSiteDate;
}
public void setRequiredOnSiteDate(Date requiredOnSiteDate) {
this.requiredOnSiteDate = requiredOnSiteDate;
}
/**
* Flag to indicate whether the packageQuantity field was the last to be
* set. To be used in the calculation of the the unitQuantity and
* packageQuantity fields if true: packageQuantity field was the last to be
* set and will be used as a priority in the calculation of the unitQuantity
* if false: unitQuantity field was the last to be set and will be used as a
* priority in the calculation of the packageQuantity
*
* Default value is false which is explicitly set to avoid confusion, we
* always initially assume unitQuantity was the last set
*/
@XmlTransient
@Transient
@JsonIgnore
private boolean packageQuantityLastSet = false;
/**
* Indicates if order was created via integration interface.
*/
@XmlAttribute
protected boolean integrated;
/**
* Indicates if this line item was added after estimate level.
*/
private boolean additional;
/**
* Indicates if this line item is a copy of an original one. This concept is
* used to allow users to change actual-level line items.
*
* @see <[CDATA[https://connect.devstream.net/display/Dev/2014/03/18/Adding+or
* +editing+items+at+shipment+level]]>
*/
private boolean copy;
@XmlAttribute
@Temporal(TemporalType.TIMESTAMP)
private Date addedToOrderDate;
@XmlAttribute
private BigDecimal sellPriceExclusiveAmount;
@XmlAttribute
private BigDecimal sellPriceInclusiveAmount;
@XmlAttribute
private String materialComposition;
private boolean elc;
private String itemTemplateDescription;
@ElementCollection(targetClass = ProductProperty.class, fetch = FetchType.EAGER)
@Enumerated(EnumType.STRING)
@CollectionTable(name = "lineitemproperties", uniqueConstraints = @UniqueConstraint(columnNames = {"lineitem_id", "lineitem_property"}))
@Column(name = "lineitem_property")
protected Set<ProductProperty> itemProperties = new HashSet<>();
private Long bulkItemId;//soft link, no foreign key
private BigDecimal childLinkedQuantity = BigDecimal.ZERO;
public LineItem() {
promotion.setLineItem(this);
}
/**
* Copy constructor. Creates a new LineItem based on the supplied LineItem's
* fields.
*
* @param lineItem The line item whose fields will be copied into this instance.
* @throws IllegalArgumentException if lineItem is null
*/
public LineItem(LineItem lineItem) {
copyFieldsFrom(lineItem);
}
/**
* Creates a new LineItem instance based on the supplied LineItem's fields.
* The difference between this method and
* {@code LineItem#LineItem(LineItem)} is that this line item will return
* true for {@code LineItem#isCopy()}.
*
* @param lineItem the line item whose fields will be copied into this instance
* @return a new LineItem instance with it's copy field set to true i.e.
* {@code LineItem#isCopy()} will be true
*/
public static LineItem createCopy(LineItem lineItem) {
LineItem copy = new LineItem(lineItem);
copy.setCopy(true);
return copy;
}
/**
* Creates a new LineItem instance with the relevant fields set that
* identifies it as a Sample item.
*
* @return a new LineItem initialised as a sample
*/
public static LineItem initialiseSample() {
return initialiseAdditionalLineItem(AdditionalLineItemType.SAMPLE);
}
/**
* Creates a new LineItem instance with the relevant fields set that
* identifies it as a Spare Part item.
*
* @return a new LineItem initialised as a spare part
*/
public static LineItem initialiseSparePart() {
return initialiseAdditionalLineItem(AdditionalLineItemType.SPARE_PART);
}
public void setState(ProductState productState) {
}
/**
* Initialises a new LineItem instance with the relevant fields set based on
* the AdditionalLineItemType supplied here.
*
* @param additionalLineItemType the line item type that determines the initial field values of
* the line item
* @return @return a new LineItem initialised with the relevant fields set
*/
private static LineItem initialiseAdditionalLineItem(AdditionalLineItemType additionalLineItemType) {
LineItem lineItem = new LineItem();
lineItem.setAdditional(true);
/*
* Only set the following fields for Samples and Spare Parts. See: Process Flow section in
* https://connect.devstream.net/display/Dev/Samples+and+Spare+Parts
*/
if (AdditionalLineItemType.SAMPLE == additionalLineItemType || AdditionalLineItemType.SPARE_PART == additionalLineItemType) {
lineItem.setCode(additionalLineItemType.getName());
lineItem.setDescription(additionalLineItemType.getName());
lineItem.setSupplierReference(additionalLineItemType.getName());
lineItem.setFreeStockType(additionalLineItemType);
}
return lineItem;
}
/**
* Copies the fields of the supplied line item into this instance's fields.
*
* @param lineItem the {@code LineItem} to copy
* @throws IllegalArgumentException if lineItem is null
*/
@Transient
public void copyFieldsFrom(LineItem lineItem) {
if (lineItem == null) {
throw new IllegalArgumentException("Line item cannot be null");
}
this.supplier = lineItem.supplier;
this.organisationalUnit = lineItem.organisationalUnit;
this.balanceClosed = lineItem.balanceClosed;
this.created = lineItem.created;
this.createDate = lineItem.createDate;
this.currency = lineItem.currency;
this.getCommissionInformation().setForeignCommissionPercentage(lineItem.getCommissionInformation().getForeignCommissionPercentage());
this.getCommissionInformation().setWarehousingCommissionPercentage(lineItem.getCommissionInformation().getWarehousingCommissionPercentage());
this.getCommissionInformation().setSourcingCommissionPercentage(lineItem.getCommissionInformation().getSourcingCommissionPercentage());
this.getCommissionInformation().setMerchandisingCommissionPercentage(
lineItem.getCommissionInformation().getMerchandisingCommissionPercentage());
this.code = lineItem.code;
this.description = lineItem.description;
this.countryOfOrigin = lineItem.countryOfOrigin;
this.supplierReference = lineItem.supplierReference;
this.barcode = lineItem.barcode;
this.lastLandedCostAmount = lineItem.lastLandedCostAmount;
this.unitType = lineItem.unitType;
this.unitQuantity = lineItem.unitQuantity;
this.unitPrice = lineItem.unitPrice;
this.unitVolume = lineItem.unitVolume;
this.unitWeight = lineItem.unitWeight;
this.packageType = lineItem.packageType;
this.packageQuantity = lineItem.packageQuantity;
this.packagePrice = lineItem.packagePrice;
this.packageVolume = lineItem.packageVolume;
this.packageWeight = lineItem.packageWeight;
this.unitsPerPackage = lineItem.unitsPerPackage;
this.exciseDuty = lineItem.exciseDuty;
this.exciseDutyPercentage = lineItem.exciseDutyPercentage;
this.dutyCharge = lineItem.dutyCharge;
this.promotion.enabled = lineItem.promotion.enabled;
this.promotion.name = lineItem.promotion.name;
this.promotion.quantity = lineItem.promotion.quantity;
this.promotion.fromDate = lineItem.promotion.fromDate;
this.promotion.toDate = lineItem.promotion.toDate;
this.promotion.lineItem = this;
this.order = lineItem.order;
this.packageQuantityLastSet = lineItem.packageQuantityLastSet;
this.weightUOM = lineItem.weightUOM;
this.volumeUOM = lineItem.volumeUOM;
this.schedule1Part1A = lineItem.schedule1Part1A == null ? null : lineItem.schedule1Part1A.clone();
this.schedule1Part2A = lineItem.schedule1Part2A == null ? null : lineItem.schedule1Part2A.clone();
this.schedule1Part2B = lineItem.schedule1Part2B == null ? null : lineItem.schedule1Part2B.clone();
this.schedule2Part1 = lineItem.schedule2Part1 == null ? null : lineItem.schedule2Part1.clone();
this.schedule2Part2 = lineItem.schedule2Part2 == null ? null : lineItem.schedule2Part2.clone();
this.schedule3Part1 = lineItem.schedule3Part1 == null ? null : lineItem.schedule3Part1.clone();
this.schedule4Part1 = lineItem.schedule4Part1 == null ? null : lineItem.schedule4Part1.clone();
this.getCommissionInformation().setForeignCommissionValueType(lineItem.getCommissionInformation().getForeignCommissionValueType());
this.getCommissionInformation().setWarehousingCommissionValueType(lineItem.getCommissionInformation().getWarehousingCommissionValueType());
this.getCommissionInformation().setSourcingCommissionValueType(lineItem.getCommissionInformation().getSourcingCommissionValueType());
this.getCommissionInformation().setMerchandisingCommissionValueType(
lineItem.getCommissionInformation().getMerchandisingCommissionValueType());
this.portHealthInspectionFee = lineItem.portHealthInspectionFee;
this.styleDescription = lineItem.description;
this.styleReference = lineItem.styleReference;
this.sellPriceExclusiveAmount = lineItem.sellPriceExclusiveAmount;
this.sellPriceInclusiveAmount = lineItem.sellPriceInclusiveAmount;
this.materialComposition = lineItem.materialComposition;
this.elc = lineItem.elc;
this.valueDeterminationNumber = lineItem.valueDeterminationNumber == null ? null : lineItem.valueDeterminationNumber;
this.factory = lineItem.getFactory();
}
@Override
public BigDecimal getUnitPrice() {
return (unitPrice == null && packagePrice != null && unitsPerPackage != null && !MathUtils.isZero(unitsPerPackage)) ? packagePrice.divide(
unitsPerPackage, MathUtils.SCALE_VERY_ACCURATE, MathUtils.ROUNDING_MODE) : unitPrice != null ? unitPrice : BigDecimal.ZERO;
}
@Override
public void setUnitPrice(BigDecimal unitPrice) {
super.setUnitPrice(unitPrice != null ? unitPrice.setScale(MathUtils.SCALE_VERY_ACCURATE, RoundingMode.HALF_UP) : null);
this.packagePrice = null;
}
public BigDecimal getUnitVolumeField() {
return unitVolume;
}
public BigDecimal getUnitWeightField() {
return unitWeight;
}
@Override
public BigDecimal getUnitWeight() {
// return (packageWeight != null && unitsPerPackage != null && !MathUtils.isZero(unitsPerPackage) && !MathUtils.isZero(packageWeight))
// ? packageWeight.divide(unitsPerPackage, MathUtils.SCALE, MathUtils.ROUNDING_MODE)
// : (unitWeight != null ? unitWeight : BigDecimal.ZERO);
return unitWeight;
}
public Order getOrder() {
return order;
}
public void setOrder(Order order) {
this.order = order;
}
public Date getCreateDate() {
return createDate;
}
public void setCreateDate(Date createDate) {
this.createDate = createDate;
}
public String getHandlingDescription() {
return handlingDescription;
}
public void setHandlingDescription(String handlingDescription) {
this.handlingDescription = handlingDescription;
}
public String getPackingInstruction() {
return packingInstruction;
}
public void setPackingInstruction(String packingInstruction) {
this.packingInstruction = packingInstruction;
}
@Override
public LineItemState getState() {
return state;
}
@Override
public void setState(LineItemState state) {
this.state = state;
}
@Override
public List<LineItemEvent> getEvents() {
return events;
}
public String getElcStyleDescription() {
return elcStyleDescription;
}
public void setElcStyleDescription(String elcStyleDescription) {
this.elcStyleDescription = elcStyleDescription;
}
@Override
public LineItemEvent getLastEvent() {
return Event.getLastEvent(events);
}
public void setEvents(List<LineItemEvent> events) {
this.events = events;
}
public BigDecimal getUnitQuantity() {
// if the packageQuantity was last set then unitQuantity needs to be recalculated
unitQuantity = (isPackageQuantityLastSet() && unitsPerPackage != null) ?
packageQuantity.multiply(unitsPerPackage).setScale(MathUtils.SCALE, MathUtils.ROUNDING_MODE) :
unitQuantity;
return unitQuantity;
}
public void setUnitQuantity(BigDecimal unitQuantity) {
if (unitQuantity != null && !unitQuantity.equals(this.unitQuantity)) {
// only if the value is changing then indicate that the unitQuantity
// was the last field to be set
setPackageQuantityLastSet(false);
}
this.unitQuantity = unitQuantity;
}
public BigDecimal getPackageQuantity() {
// if the unitQuantity was last set then packageQuantity needs to be recalculated
packageQuantity =
(isUnitQuantityLastSet() && unitsPerPackage != null && !MathUtils.isZero(unitsPerPackage)) ? unitQuantity.divide(unitsPerPackage,
MathUtils.SCALE, MathUtils.ROUNDING_MODE) : packageQuantity;
return packageQuantity;
}
public void setPackageQuantity(BigDecimal packageQuantity) {
if (packageQuantity != null && !packageQuantity.equals(this.packageQuantity)) {
// only if the value is changing then indicate that the unitQuantity
// was the last field to be set
setPackageQuantityLastSet(true);
}
this.packageQuantity = packageQuantity;
}
public BigDecimal getRoundedPackageQuantity() {
if (packageQuantity != null) {
roundedPackageQuantity = packageQuantity.setScale(0, RoundingMode.UP);
}
return roundedPackageQuantity;
}
/**
* Setter is private, this field will only be controlled from inside this
* class by rounding t.
*
* @param roundedPackageQuantity
* @see
*/
@SuppressWarnings("unused")
private void setRoundedPackageQuantity(BigDecimal roundedPackageQuantity) {
this.roundedPackageQuantity = roundedPackageQuantity;
}
public BigDecimal getPackagePrice() {
return (unitPrice != null && unitsPerPackage != null) ? unitPrice.multiply(unitsPerPackage).setScale(MathUtils.SCALE,
MathUtils.ROUNDING_MODE) : packagePrice;
}
public void setPackagePrice(BigDecimal packagePrice) {
this.packagePrice = packagePrice;
}
@Override
public BigDecimal getPackageVolume() {
if (packageVolume != null && !MathUtils.isZero(packageVolume)) {
return packageVolume;
}
ItemProductUtil.calculateAndSetVolume(this, this.packageVolume, this.unitVolume);
return this.packageVolume;
}
@Override
public BigDecimal getPackageWeight() {
// return packageWeight != null ? packageWeight : (unitWeight != null && unitsPerPackage != null
// && !MathUtils.isZero(unitWeight)
// && !MathUtils.isZero(unitsPerPackage)) ? unitWeight.multiply(unitsPerPackage).setScale(MathUtils.SCALE,
// MathUtils.ROUNDING_MODE) : packageWeight;
return packageWeight;
}
public BigDecimal getTotalUnitWeight() {
return (getUnitWeight() != null && unitQuantity != null) ?
unitQuantity.multiply(getUnitWeight()).setScale(MathUtils.SCALE_DISPLAY, MathUtils.ROUNDING_MODE)
: BigDecimal.ZERO;
}
public BigDecimal getTotalUnitVolume() {
return (getUnitVolume() != null && unitQuantity != null) ?
unitQuantity.multiply(getUnitVolume()).setScale(MathUtils.SCALE_DISPLAY, MathUtils.ROUNDING_MODE)
: BigDecimal.ZERO;
}
public BigDecimal getTotalPackageQuantity() {
// if the unitQuantity was last set then packageQuantity needs to be recalculated
packageQuantity =
(isUnitQuantityLastSet() && unitsPerPackage != null && !MathUtils.isZero(unitsPerPackage))
? unitQuantity.divide(unitsPerPackage, MathUtils.SCALE_DISPLAY, MathUtils.ROUNDING_MODE)
: packageQuantity;
return packageQuantity;
}
public BigDecimal getUnitQuantityReceived() {
return unitQuantityReceived;
}
public void setUnitQuantityReceived(BigDecimal unitQuantityReceived) {
this.unitQuantityReceived = unitQuantityReceived;
}
public BigDecimal getUnitQuantityInvoiced() {
return unitQuantityInvoiced;
}
public void setUnitQuantityInvoiced(BigDecimal unitQuantityInvoiced) {
this.unitQuantityInvoiced = unitQuantityInvoiced;
}
public BigDecimal getUnitQuantityAvailable() {
return unitQuantityAvailable;
}
public void setUnitQuantityAvailable(BigDecimal unitQuantityAvailable) {
this.unitQuantityAvailable = unitQuantityAvailable;
}
public BigDecimal getUnitQuantityReserved() {
return unitQuantityReserved;
}
public void setUnitQuantityReserved(BigDecimal unitQuantityReserved) {
this.unitQuantityReserved = unitQuantityReserved;
}
public BigDecimal getUnitQuantityToBePacked() {
return unitQuantityToBePacked;
}
public void setUnitQuantityToBePacked(BigDecimal unitQuantityToBePacked) {
this.unitQuantityToBePacked = unitQuantityToBePacked;
}
public BigDecimal getUnitQuantityPacked() {
return unitQuantityPacked;
}
public void setUnitQuantityPacked(BigDecimal unitQuantityPacked) {
this.unitQuantityPacked = unitQuantityPacked;
}
public boolean isBalanceClosed() {
return balanceClosed;
}
public void setBalanceClosed(boolean balanceClosed) {
this.balanceClosed = balanceClosed;
}
public BigDecimal getUnitSellingPrice() {
return unitSellingPrice;
}
public void setUnitSellingPrice(BigDecimal unitSellingPrice) {
this.unitSellingPrice = unitSellingPrice;
}
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 getLastLandedCostAmount() {
return this.lastLandedCostAmount;
}
public void setLastLandedCostAmount(BigDecimal lastLandedCostAmount) {
this.lastLandedCostAmount = lastLandedCostAmount;
}
public BigDecimal getSellingPrice() {
return this.sellingPrice;
}
public void setSellingPrice(BigDecimal sellingPrice) {
this.sellingPrice = sellingPrice;
}
public BigDecimal getDutyCharge() {
return this.dutyCharge;
}
public void setDutyCharge(BigDecimal dutyCharge) {
this.dutyCharge = dutyCharge;
}
public BigDecimal getExciseDuty() {
return this.exciseDuty;
}
public void setExciseDuty(BigDecimal exciseDuty) {
this.exciseDuty = exciseDuty;
}
@OneToOne(mappedBy = "lineItem")
public LineItemPromotion getPromotion() {
return promotion;
}
public void setPromotion(LineItemPromotion promotion) {
this.promotion = promotion;
promotion.setLineItem(this);
}
@Override
public String toString() {
return "LineItem{" +
"code='" + code + '\'' +
"id='" + getId() + '\'' +
", description='" + description + '\'' +
'}';
}
@Override
public String getDescription() {
return description;
}
public BigDecimal getTotalCost() {
BigDecimal totalCost = null;
// don't want to display a zero total if we don't have unit price or quantity set
if (unitQuantity != null && unitPrice != null) {
totalCost = MathUtils.multiplyVA(unitQuantity, unitPrice);
}
return totalCost;
}
public BigDecimal getTotalSalesValue() {
BigDecimal totalSalesValue = BigDecimal.ZERO;
// don't want to display a zero total if we don't have unit price or quantity set
if (unitQuantity != null && unitSellingPrice != null) {
totalSalesValue = MathUtils.multiplyVA(unitQuantity, unitSellingPrice);
}
return totalSalesValue;
}
public UnitType getUnitType() {
return unitType;
}
public void setUnitType(UnitType unitType) {
this.unitType = unitType;
}
public PackageType getPackageType() {
return packageType;
}
public void setPackageType(PackageType packageType) {
this.packageType = packageType;
}
/**
* Sets the valid flag of each duty schedule, if it's not null, to the value
* supplied.
*
* @param valid the new value of the valid flag
*/
public void setDutyInformationValid(boolean valid) {
setScheduleValidFlag(schedule1Part1A, valid);
setScheduleValidFlag(schedule1Part2A, valid);
setScheduleValidFlag(schedule1Part2B, valid);
setScheduleValidFlag(schedule2Part1, valid);
setScheduleValidFlag(schedule2Part2, valid);
setScheduleValidFlag(schedule3Part1, valid);
setScheduleValidFlag(schedule4Part1, valid);
}
/**
* Determines if this line item is tariffed.
*
* @return true if this line item's state equals
* {@link LineItemState#TARIFFED}, false otherwise
*/
public boolean isTariffed() {
return LineItemState.TARIFFED.equals(state);
}
/**
* Convenience method to be used to check if the packageQuantity was set
* last over the unitQuantity field.
*
* @return the packageQuantityLastSet flag, true if the packageQuantity
* field was set last over the unitQuantity field
*/
public boolean isPackageQuantityLastSet() {
return (packageQuantityLastSet && packageQuantity != null);
}
/**
* Convenience method to be used to check if the unitQuantity was set last
* over the packageQuantity field.
*
* @return the opposite of the packageQuantityLastSet flag, true if the
* unitQuantity field was set last over the packageQuantity field
*/
public boolean isUnitQuantityLastSet() {
return (!packageQuantityLastSet && unitQuantity != null);
}
/**
* Convenience method to be used to check if the packageQuantity was a
* calculated value based on the unit quantity divided by the units per
* package.
*
* @return true if packageQuantityLastSet is false and unitsPerPackage != null
*/
public boolean isPackageQuantityACalculatedValue() {
return (!packageQuantityLastSet && packageQuantity != null && unitsPerPackage != null);
}
/**
* Convenience method to be used to check if the unitQuantity was a
* calculated value based on the package quantity multiplied by the units
* per package.
*
* @return true if packageQuantityLastSet is true and unitsPerPackage != null
*/
public boolean isUnitQuantityACalculatedValue() {
return (packageQuantityLastSet && unitQuantity != null && unitsPerPackage != null);
}
/**
* Private method, only this class can control this flag.
*
* @param packageQuantityLastSet
*/
private void setPackageQuantityLastSet(boolean packageQuantityLastSet) {
this.packageQuantityLastSet = packageQuantityLastSet;
}
/**
* Sets the schedule's valid flag to the valid value supplied if the
* schedule is not null.
*
* @param schedule the schedule whose valid flag to set
* @param valid the new value of the schedule's valid flag
*/
private void setScheduleValidFlag(DutySchedule schedule, boolean valid) {
if (schedule != null) {
schedule.setValid(valid);
}
}
public boolean isItemDutiesUpdated() {
return isItemDutiesUpdated;
}
public void setItemDutiesUpdated(boolean isItemDutiesUpdated) {
this.isItemDutiesUpdated = isItemDutiesUpdated;
}
@Override
public void accept(CostingVisitor costingVisitor) {
costingVisitor.visit(this);
}
/**
* Requirement is to always display line items in the order that they are
* created in.
*
* @param li
*/
@Override
public int compareTo(LineItem li) {
CompareToBuilder compareToBuilder = new CompareToBuilder();
return compareToBuilder.append(position, li.getPosition())
.append(created, li.getCreated()).append(code, li.getCode()).toComparison();
}
@Override
public boolean inNonEditableState() {
return false;
}
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;
}
@Override
public boolean isAdditional() {
return additional;
}
public boolean isIntegrated() {
return integrated;
}
public void setAdditional(boolean additional) {
this.additional = additional;
}
public boolean isCopy() {
return copy;
}
public void setCopy(boolean copy) {
this.copy = copy;
}
@Override
public String getKey() {
return new StringBuilder(toString()).append("-").append(hashCode()).toString();
}
public void setIntegrated(boolean integrated) {
this.integrated = integrated;
}
@Override
public boolean isSample() {
return additional && (AdditionalLineItemType.SAMPLE.getName().equals(code) || freeStockType == AdditionalLineItemType.SAMPLE);
}
@Override
public boolean isSparePart() {
return additional && (AdditionalLineItemType.SPARE_PART.getName().equals(code) || freeStockType == AdditionalLineItemType.SPARE_PART);
}
public boolean equalsOnBaseFields(Object obj) {
return super.equals(obj);
}
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (this == obj) {
return true;
}
if (!HibernateUtils.proxyClassEquals(this, obj)) {
return false;
}
LineItem other = (LineItem) obj;
return new EqualsBuilder().appendSuper(super.equals(obj)).append(copy, other.copy)
.append(lineNumber, other.getLineNumber()).isEquals();
}
@Override
public int hashCode() {
return new HashCodeBuilder().appendSuper(super.hashCode()).append(copy).append(lineNumber).toHashCode();
}
public Date getAddedToOrderDate() {
return addedToOrderDate;
}
public void setAddedToOrderDate(Date addedToOrderDate) {
this.addedToOrderDate = addedToOrderDate;
}
public BigDecimal getSellPriceExclusiveAmount() {
return sellPriceExclusiveAmount;
}
public void setSellPriceExclusiveAmount(BigDecimal sellPriceExclusiveAmount) {
if (hangerType == null) {
this.sellPriceExclusiveAmount = sellPriceExclusiveAmount;
} else {
this.sellPriceExclusiveAmount = BigDecimal.ZERO;
}
}
public BigDecimal getSellPriceInclusiveAmount() {
return sellPriceInclusiveAmount;
}
public void setSellPriceInclusiveAmount(BigDecimal sellPriceInclusiveAmount) {
if (hangerType == null) {
this.sellPriceInclusiveAmount = sellPriceInclusiveAmount;
} else {
this.sellPriceInclusiveAmount = BigDecimal.ZERO;
}
}
public String getMaterialComposition() {
return materialComposition;
}
public void setMaterialComposition(String materialComposition) {
this.materialComposition = materialComposition;
}
public ItemType getItemType() {
if (itemType == null)
itemType = ItemType.GENERAL;
return itemType;
}
public void setItemType(ItemType itemtype) {
this.itemType = itemtype;
getItacPermit().setRebateSchedule(itemType);
}
public HangerLineItem getHangerItem() {
return hangerLineItem;
}
public void setHangerItem(HangerLineItem hangerLineItem) {
this.hangerLineItem = hangerLineItem;
}
public boolean isFromApi() {
return fromApi;
}
public void setFromApi(boolean fromApi) {
this.fromApi = fromApi;
}
public boolean isElc() {
return elc;
}
public void setElc(boolean elc) {
this.elc = elc;
}
public boolean isLineItem() {
return true;
}
public String getItemTemplateDescription() {
return itemTemplateDescription;
}
public void setItemTemplateDescription(String itemTemplateDescription) {
this.itemTemplateDescription = itemTemplateDescription;
}
public Integer getLineNumber() {
return lineNumber;
}
public void setLineNumber(Integer lineNumber) {
this.lineNumber = lineNumber;
}
public Integer getPosition() {
return position;
}
public void setPosition(Integer position) {
this.position = position;
}
public Set<ProductProperty> getItemProperties() {
return itemProperties;
}
public void setItemProperties(Set<ProductProperty> itemProperties) {
this.itemProperties = itemProperties;
}
public Type getElcOrFull() {
return this.isElc() ? Type.ELC : Type.FULL;
}
public List<AddedCommentIncCost> getComments() {
return comments;
}
public void setComments(List<AddedCommentIncCost> comments) {
this.comments = comments;
}
public HangerType getHangerType() {
return hangerType;
}
public void setHangerType(HangerType hangerType) {
this.hangerType = hangerType;
if (hangerType != null) {
this.sellPriceInclusiveAmount = BigDecimal.ZERO;
this.sellPriceExclusiveAmount = BigDecimal.ZERO;
}
}
public Long getParentLineItemId() {
return parentLineItemId;
}
public void setParentLineItemId(Long parentLineItemId) {
this.parentLineItemId = parentLineItemId;
}
/**
* Creates a new LineItem instance based on the supplied LineItem's fields.
* The difference between this method and
* {@code LineItem#LineItem(LineItem)} is that this line item will return
* true for {@code LineItem#isCopy()}.
*
* @param lineItem the line item whose fields will be copied into this instance
* @return a new LineItem instance with it's copy field set to true i.e.
* {@code LineItem#isCopy()} will be true
*/
public static LineItem createHangerItem(LineItem lineItem) {
LineItem copy = new LineItem(lineItem);
copy.setCopy(true);
return copy;
}
@Override
public boolean applyItacPermit() {
return itemType == ItemType.GENERAL_REBATE || itemType == ItemType.INDUSTRIAL_REBATE;
}
@Override
public Set<ProductProperty> getProperties() {
return getItemProperties();
}
@Override
public BigDecimal getPenaltyAmount() {
return null;
}
@Override
public void setPenaltyAmount(BigDecimal penaltyAmount) {
}
public Long getBulkItemId() {
return bulkItemId;
}
public void setBulkItemId(Long bulkItemId) {
this.bulkItemId = bulkItemId;
}
public BigDecimal getChildLinkedQuantity() {
return childLinkedQuantity;
}
public void setChildLinkedQuantity(BigDecimal childLinkedQuantity) {
this.childLinkedQuantity = childLinkedQuantity;
}
public Set<AdditionalNotes> getAdditionalNotes() {
return additionalNotes;
}
public void setAdditionalNotes(Set<AdditionalNotes> additionalNotes) {
this.additionalNotes = additionalNotes;
}
@Override
public boolean inTariffiedState() {
return state == LineItemState.TARIFFED;
}
public AdditionalLineItemType getFreeStockType() {
return freeStockType;
}
public void setFreeStockType(AdditionalLineItemType freeStockType) {
this.freeStockType = freeStockType;
if (freeStockType != null && freeStockType.isFreeStock()) {
this.additional = true;
}
}
public String getImplementationType() {
return "ITEM";
}
public HomologationStatus getHomologationStatus() {
return homologationStatus;
}
public void setHomologationStatus(HomologationStatus homologationStatus) {
this.homologationStatus = homologationStatus;
}
public boolean equalsGRRItem(GoodsReceivedReceiptItem item) {
if (item != null && getCode().equals(item.getReference()) &&
Objects.equals(lineNumber, item.getLineNumber()) &&
getOrganisationalUnit().equals(item.getOrganisationalUnit())) {
return true;
}
return false;
}
public boolean equalsReceiptItem(String reference, Integer lineNumber, String department, Country coo) {
if (getCode().equals(reference) && Objects.equals(this.lineNumber, lineNumber) && getCountryOfOrigin().equals(coo)
/*getOrganisationalUnit().equals(item.getOrganisationalUnit())*/) {
return true;
}
return false;
}
}