package com.dev.swms.server.model.receiving;

import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;

import com.dev.swms.server.model.base.Address;
import com.dev.swms.server.model.base.Contact;
import com.dev.swms.server.model.base.Structure;
import com.dev.swms.server.model.base.Warehouse;
import com.dev.energy.server.model.VersionalEntity;
import com.dev.energy.server.web.security.UserHolder;

public class ReceivingDoc extends VersionalEntity {
	private static final long serialVersionUID = -151905191579126529L;
	/** 所属仓库 */
	private Warehouse warehouse;
	/** 所属客户 */
	private Structure company;
	/** 收货单号 */
	private String code;
	/** 状态 */
	private String status;
	/** 收货单类型 */
	private String type;
	/** 相关单据号1 */
	private String relatedBill1;
	/** 相关单据号2 */
	private String relatedBill2;
	/** 相关单据号3 */
	private String relatedBill3;
	/** 订单日期 */
	private Date orderDate;
	/** 预计到货日期 */
	private Date estimateDate;
	/** 收货日期 */
	private Date receivedDate;
	/** 发货方名称 */
	private String fromName;
	/** 发货方地址 */
	private Address fromAddress;
	/** 发货方联系方式 */
	private Contact fromContact;
	/** 预期数量 */
	private double expectedQuantity;
	/** 实收数量 */
	private double receivedQuantity;
	/** ASN数量*/
    private double asnQuantity;
	/** 收货单明细 */
	private Set<ReceivingDocDetail> receivingDocDetails;
	/** 收货记录明细 */
	private Set<ReceivedRecord> receivedRecords;
	/** 最后修改人ID * */
	private Long userID;
	/** 最后修改人姓名 * */
	private String userName;
	/** 最后修改时间 * */
	private Date updateTime;
	/** 单据类型 */
	private String billType;
	/** 集货编号 */
	private String collectNo;
	/** 是否有托盘收货（默认无） */
	private int hasLP = 0;

	protected ReceivingDoc() {

	}

	public int getHasLP() {
		return hasLP;
	}

	public void setHasLP(int hasLP) {
		this.hasLP = hasLP;
	}

	public String getCollectNo() {
		return collectNo;
	}

	public void setCollectNo(String collectNo) {
		this.collectNo = collectNo;
	}

	public String getCode() {
		return code;
	}

	public void setCode(String code) {
		this.code = code;
	}

	public String getType() {
		return type;
	}

	public void setType(String type) {
		this.type = type;
	}

	public Structure getCompany() {
		return company;
	}

	public void setCompany(Structure company) {
		this.company = company;
	}

	public Date getEstimateDate() {
		return estimateDate;
	}

	public void setEstimateDate(Date estimateDate) {
		this.estimateDate = estimateDate;
	}

	public double getExpectedQuantity() {
		return expectedQuantity;
	}

	public void setExpectedQuantity(double expectedQuantity) {
		this.expectedQuantity = expectedQuantity;
	}

	public Address getFromAddress() {
		return fromAddress;
	}

	public void setFromAddress(Address fromAddress) {
		this.fromAddress = fromAddress;
	}

	public Contact getFromContact() {
		return fromContact;
	}

	public void setFromContact(Contact fromContact) {
		this.fromContact = fromContact;
	}

	public String getFromName() {
		return fromName;
	}

	public void setFromName(String fromName) {
		this.fromName = fromName;
	}

	public Date getOrderDate() {
		return orderDate;
	}

	public void setOrderDate(Date orderDate) {
		this.orderDate = orderDate;
	}

	public Date getReceivedDate() {
		return receivedDate;
	}

	public void setReceivedDate(Date receivedDate) {
		this.receivedDate = receivedDate;
	}

	public double getReceivedQuantity() {
		return receivedQuantity;
	}

	public void setReceivedQuantity(double receivedQuantity) {
		this.receivedQuantity = receivedQuantity;
	}

	public String getRelatedBill1() {
		return relatedBill1;
	}

	public void setRelatedBill1(String relatedBill1) {
		this.relatedBill1 = relatedBill1;
	}

	public String getRelatedBill2() {
		return relatedBill2;
	}

	public void setRelatedBill2(String relatedBill2) {
		this.relatedBill2 = relatedBill2;
	}

	public String getRelatedBill3() {
		return relatedBill3;
	}

	public void setRelatedBill3(String relatedBill3) {
		this.relatedBill3 = relatedBill3;
	}

	public String getStatus() {
		return status;
	}

	public void setStatus(String status) {
		this.status = status;
	}

	public Warehouse getWarehouse() {
		return warehouse;
	}

	public void setWarehouse(Warehouse warehouse) {
		this.warehouse = warehouse;
	}

	public Set<ReceivingDocDetail> getReceivingDocDetails() {
		return receivingDocDetails;
	}

	public void setReceivingDocDetails(
			Set<ReceivingDocDetail> receivingDocDetails) {
		this.receivingDocDetails = receivingDocDetails;
	}

	public Set<ReceivedRecord> getReceivedRecords() {
		return receivedRecords;
	}

	public void setReceivedRecords(Set<ReceivedRecord> receivedRecords) {
		this.receivedRecords = receivedRecords;
	}

	public Date getUpdateTime() {
		return updateTime;
	}

	public void setUpdateTime(Date updateTime) {
		this.updateTime = updateTime;
	}

	public Long getUserID() {
		return userID;
	}

	public void setUserID(Long userID) {
		this.userID = userID;
	}

	public String getUserName() {
		return userName;
	}

	public void setUserName(String userName) {
		this.userName = userName;
	}

	/**
	 * 记录收货单的最新修改用户和修改时间信息
	 * 
	 */
	public void setUserTracking() {
		this.setUserID(UserHolder.getUser().getId());
		this.setUserName(UserHolder.getUser().getName());
		this.setUpdateTime(new Date());
	}

	/**
	 * 删除收货单明细，并扣减收货单的期待数量
	 * 
	 * @param receivingDocDetailIds
	 *            待删除收货单明细的ID集合
	 */
	public void removeDetails(List<Long> receivingDocDetailIds) {
		if (receivingDocDetails != null
				&& ReceivingDocStatus.OPEN.equals(this.status)) {
			Set<ReceivingDocDetail> toBeRemoved = new HashSet<ReceivingDocDetail>();
			for (ReceivingDocDetail detail : receivingDocDetails) {
				if (receivingDocDetailIds.contains(detail.getId()) && detail.getAsnQuantity()<=0) {
					toBeRemoved.add(detail);
				}
			}
			for (ReceivingDocDetail detail : toBeRemoved) {
				receivingDocDetails.remove(detail);
				this.expectedQuantity -= detail.getExpectedQuantity();
			}
			setUserTracking();
		}
	}

	/**
	 * 增加收货单明细，并增加收货单的期待数量
	 * 
	 * @param receivingDocDetail
	 *            待增加的收货单明细
	 */
	public void addReceivingDocDetail(ReceivingDocDetail receivingDocDetail) {
		receivingDocDetail.setReceivingDoc(this);
		this.receivingDocDetails.add(receivingDocDetail);
		this.expectedQuantity += receivingDocDetail.getExpectedQtyOfMasterUnit();
		setUserTracking();
	}

	/**
	 * 增加收货单和收货单明细的期待数量
	 * 
	 * @param docDetail
	 *            待增加期待数量的收货单明细
	 * @param quantity
	 *            待增加的期待数量(包装数量)
	 */
	public void addExpectedQuantity(ReceivingDocDetail docDetail,
			double quantity) {
		this.expectedQuantity += quantity*docDetail.getPackageUnit().getConvertFigure();
		docDetail.addExpectedQuantity(quantity);
		setUserTracking();
	}

	/**
	 * 检查收货单是否所有明细都完成收货
	 * 
	 * @return true-收货完毕 false－未完全收货
	 */
	public boolean isAllReceived() {
		for (ReceivingDocDetail detail : this.getReceivingDocDetails()) {
			if (detail.getExpectedQtyOfMasterUnit() != detail.getReceivedQuantity()) {
				return false;
			}
		}
		return true;
	}

	/**
	 * 激活收货单－设置收货单“打开”状态为“生效”
	 * 
	 * @return true-成功 false－失败
	 */
	public boolean active() {

		if (this.getReceivingDocDetails().size()>0
				&&ReceivingDocStatus.OPEN.equals(this.getStatus()) ) {

			this.setStatus(ReceivingDocStatus.ACTIVE);
			this.setUserTracking();
			return true;

		}
		return false;
	}

	/**
	 * 取消激活收货单－设置收货单“生效”状态为“打开”
	 * 已收货的单据不能取消激活
	 * @return true-成功 false－失败
	 */
	public boolean inactive() {
		if (ReceivingDocStatus.ACTIVE.equals(this.getStatus()) && this.getReceivedQuantity()==0) {
			this.setStatus(ReceivingDocStatus.OPEN);
			setUserTracking();
			return true;
		}
		return false;
	}

	/**
	 * 关闭收货单－设置收货单“收货”状态为“关闭”
	 * 
	 * @return true-成功 false－失败
	 */
	public boolean close() {
		if (ReceivingDocStatus.RECEIVING.equals(this.getStatus())) {
			this.setStatus(ReceivingDocStatus.CLOSE);
			setUserTracking();
			return true;
		}
		return false;
	}

	/**
	 * 取消收货单－设置收货单“打开”状态为“取消”
	 * 
	 * @return true-成功 false－失败
	 */
	public boolean cancel() {
		if (ReceivingDocStatus.OPEN.equals(this.getStatus())) {
			this.setStatus(ReceivingDocStatus.CANCEL);
			setUserTracking();
			return true;
		}
		return false;
	}

	public String getBillType() {
		return billType;
	}

	public void setBillType(String billType) {
		this.billType = billType;
	}

	public double getAsnQuantity() {
		return asnQuantity;
	}

	public void setAsnQuantity(double asnQuantity) {
		this.asnQuantity = asnQuantity;
	}

	public void addReceivedQuantity(double quantity){
    	this.receivedQuantity+=quantity;
    }

	public boolean equals(final Object other) {
		if (!(other instanceof ReceivingDoc))
			return false;
		ReceivingDoc castOther = (ReceivingDoc) other;
		return new EqualsBuilder().append(warehouse, castOther.getWarehouse())
				.append(company, castOther.getCompany()).append(code,
						castOther.getCode()).append(type, castOther.getType())
				.isEquals();
	}

	public int hashCode() {
		return new HashCodeBuilder().append(warehouse).append(company).append(
				code).append(type).toHashCode();
	}
}
