package com.dev.swms.server.service.inventory.pojo;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.lang.StringUtils;

import com.dev.swms.server.model.base.BOMComponent;
import com.dev.swms.server.model.base.BillType;
import com.dev.swms.server.model.base.Item;
import com.dev.swms.server.model.base.ItemKey;
import com.dev.swms.server.model.base.Location;
import com.dev.swms.server.model.base.LotInfo;
import com.dev.swms.server.model.base.PackageUnit;
import com.dev.swms.server.model.inventory.Inventory;
import com.dev.swms.server.model.inventory.ItemKeyInventory;
import com.dev.swms.server.model.inventory.ProcessDoc;
import com.dev.swms.server.model.inventory.ProcessDocBOMDetail;
import com.dev.swms.server.model.inventory.ProcessDocDetail;
import com.dev.swms.server.model.inventory.ProcessDocStatus;
import com.dev.swms.server.model.inventory.Stock;
import com.dev.swms.server.model.inventory.Task;
import com.dev.swms.server.service.base.ItemManager;
import com.dev.swms.server.service.base.WarehouseManager;
import com.dev.swms.server.service.inventory.InventoryManager;
import com.dev.swms.server.service.inventory.ProcessDocManager;
import com.dev.swms.server.service.picking.allocate.AutoAllocator;
import com.dev.swms.server.service.sequence.BussinessCodeManager;
import com.dev.swms.server.web.filter.WarehouseHolder;
import com.dev.energy.server.exception.BusinessException;
import com.dev.energy.server.service.pojo.DefaultBaseManager;
import com.dev.energy.server.util.LocalizedMessage;

public class DefaultProcessDocManager extends DefaultBaseManager implements
		ProcessDocManager {

	protected final WarehouseManager warehouseManager;
	
	protected final AutoAllocator autoAllocator;
	
	protected final ItemManager itemManager;
	
	protected final InventoryManager inventoryManager;
	protected final BussinessCodeManager bussinessCodeManager;
	
	public DefaultProcessDocManager(WarehouseManager warehouseManager,AutoAllocator autoAllocator,
			ItemManager itemManager, InventoryManager inventoryManager,BussinessCodeManager bussinessCodeManager){
		this.warehouseManager = warehouseManager;
		this.autoAllocator = autoAllocator;
		this.itemManager = itemManager;
		this.inventoryManager = inventoryManager;
		this.bussinessCodeManager = bussinessCodeManager;
	}
	
	public void addProcessDocDetail(Long processDocId, ProcessDocDetail detail) {
		ProcessDoc processDoc = commonDao.load(ProcessDoc.class, processDocId);
		if (detail.getQuantity() <= 0) {
			throw new BusinessException("docDetail.add.quantityError");
		}
	
		if (ProcessDocStatus.INPUT.equals(processDoc.getStatus())) {
			Item item = this.commonDao.load(Item.class,detail.getItem().getId());
			itemManager.formatLotInfo(item, detail.getLotInfo(), Boolean.TRUE);
			PackageUnit unit = commonDao.load(PackageUnit.class, detail.getPackageUnit().getId());
			if (!unit.getItem().getId().equals(detail.getItem().getId())) {
				throw new BusinessException("docDetail.itemPackageUnit.disMatch");
			}
			
			//新增明细
			if (detail.isNew()) {
				detail.setItem(item);
				detail.setPackageUnit(unit);
				detail.setAllocatedQuantity(0.0);
				detail.setPickedQuantity(0.0);
				detail.setProcessQuantity(0.0);
				if (processDoc.getProcessDocDetailByCondition(detail.getItem(), detail.getLotInfo(), detail.getPackageUnit()) != null) {
					throw new BusinessException("docDetail.add.uniqueError");
				}
				processDoc.addProcessDocDetail(detail);
			//修改明细
			} else {
			    double newQuantity = detail.getQuantity();
			    double deltaQuantity = newQuantity - getProcessDocDetailExpectedQuantity(detail.getId()).doubleValue();
			    if (newQuantity < 0) {
			    	throw new BusinessException("receivingDocDetail.expectedQuantity.error");
			    }
			    detail.setProcessDoc(processDoc);
			    detail.setItem(item);
			    detail.setPackageUnit(unit);
			    detail.setAllocatedQuantity(0.0);
				detail.setPickedQuantity(0.0);
				detail.setProcessQuantity(0.0);
			    processDoc.addQuantity(detail, deltaQuantity);
				commonDao.store(detail);
			    if (detail.getQuantity() <= 0) {
			    	processDoc.getDetails().remove(detail);
			    }
			}
			commonDao.store(processDoc);
		}
	}
	@SuppressWarnings("unchecked")
	private Double getProcessDocDetailExpectedQuantity(Long detailId){
		String hsql = "select detail.quantity from ProcessDocDetail detail where detail.id="+detailId;
		List result = this.commonDao.findByQuery(hsql);
		if(result.size()==1){
			return (Double)result.get(0);
		}
		return null;
	}

	public void saveProcessDoc(ProcessDoc processDoc) {
		//保存加工单
		if (processDoc.isNew()) {
			processDoc.setWarehouse(WarehouseHolder.getWarehouse());
			processDoc.setStatus(ProcessDocStatus.INPUT);
			processDoc.setUserTracking();
			processDoc.setQuantity(.0);
			processDoc.setAllocatedQuantity(.0);
			processDoc.setPickedQuantity(.0);
			processDoc.setProcessQuantity(.0);
			BillType billType = (BillType)this.commonDao.findByNamedQueryUniqueResult("getBillTypeByCompanyAndCode",
					new String[]{"companyId","code"},new Object[]{processDoc.getCompany().getId(), ProcessDoc.PROCESS_DOC});
			if(billType == null){
				throw new BusinessException("当前货主下没有加工单据类型！");
			}
			processDoc.setBillType(billType);
			processDoc.setCode(bussinessCodeManager.getCodeByBillType(billType, WarehouseHolder.getWarehouse().getId()));
		}
		this.store(processDoc);
	}

	public void delProcessDocDetail(Long processDocId,List<Long> ids) {
		ProcessDoc processDoc = this.commonDao.load(ProcessDoc.class,processDocId);
		processDoc.removeDetails(ids);
	}

	public void cancelProcessDoc(List<Long> ids) {
		List<ProcessDoc> processDocs = this.commonDao.loadAll(ProcessDoc.class,ids.toArray(new Long[(ids.size())]));
		for(ProcessDoc doc:processDocs){
			doc.setStatus(ProcessDocStatus.CANCEL);
			doc.setUserTracking();
		}
	}

	public void activeProcessDoc(List<Long> ids) {
		List<ProcessDoc> processDocs = this.commonDao.loadAll(ProcessDoc.class,ids.toArray(new Long[(ids.size())]));
		for(ProcessDoc doc:processDocs){
			doc.setStatus(ProcessDocStatus.ACTIVE);
			doc.setUserTracking();
		}
	}

	public void inActiveProcessDoc(List<Long> ids) {
		List<ProcessDoc> processDocs = this.commonDao.loadAll(ProcessDoc.class,ids.toArray(new Long[(ids.size())]));
		for(ProcessDoc doc:processDocs){
			doc.setStatus(ProcessDocStatus.INPUT);
			doc.setUserTracking();
		}
	}

	public void delProcessDoc(List<Long> ids) {
		List<ProcessDoc> processDocs = this.commonDao.loadAll(ProcessDoc.class,ids.toArray(new Long[(ids.size())]));
		for(ProcessDoc doc:processDocs){
			doc.getDetails().clear();
			doc.getBomDetails().clear();
			this.commonDao.delete(doc);
		}
	}
	
	

//	加工处理-------------------------------------------------------------------------------
	@SuppressWarnings("unchecked")
	public void process(Long processDocId, Map details) {
		ProcessDoc processDoc = this.commonDao.load(ProcessDoc.class,processDocId);
		if(processDoc.getStatus().equals(ProcessDocStatus.PROCESS)){
			throw new BusinessException("processDoc.be.processed");
		}
		Location processLoc = processDoc.getProcessLoc();
		for(Iterator it = details.entrySet().iterator();it.hasNext();){
			Map.Entry entry = (Entry) it.next();
			Long detailId = (Long) entry.getKey();
			List value = (List) entry.getValue();
			Double processQty = Double.valueOf(String.valueOf(value.get(0)));
			
			ProcessDocDetail detail = this.commonDao.load(ProcessDocDetail.class,detailId);
			if(processQty>detail.getPickedQuantity()){
				throw new BusinessException("processQty.big.pickedQuantity");
			}
			detail.process(processQty);
			
			ItemKey key = this.itemManager.getItemKey(new ItemKey(
					"", detail.getItem(), detail.getLotInfo(), new Date(), detail.getProcessDoc().getCode(),null), Boolean.TRUE,null);
			this.inventoryManager.processUp(processLoc.getId(),key,processQty,detail.getPackageUnit().getId(),
					null, Inventory.STATUS_VALID, new Date(), processDoc,Boolean.FALSE,Boolean.FALSE);
		}
		//加工后需要减除虚拟加工库位上面的数量
		List<Inventory> inventorys = this.commonDao.findByNamedQuery("getInventoriesByLocationId", 
				new String[] { "warehouseId","locationId" }, 
				new Object[] {processDoc.getWarehouse().getId(),processDoc.getProcessLoc().getId() });
		for(ProcessDocBOMDetail bomDetail:processDoc.getBomDetails()){
			if(bomDetail.getProcessQuantity()==.0){
				continue;
			}
			double totalQty = bomDetail.getProcessQuantity();
			for(Inventory inventory:inventorys){
				if(isPeak(inventory, bomDetail.getItem(), null)){
					double quantity = totalQty>inventory.getAvaliableQuantity()?inventory.getAvaliableQuantity():totalQty;
                    //扣减库存
					if(quantity==.0){
						continue;
					}
					this.inventoryManager.processDown(inventory.getId(),quantity,processDoc);
					totalQty -= quantity;
					if(totalQty==.0){
						break;
					}
				}
			}
		}
	}
	
	/**
	 * 判断子件明细与库存记录是否对应
	 * @param inventory
	 * @param detail
	 * @return
	 */
	private boolean isPeak(Inventory inventory, Item item, LotInfo lotInfo){
		ItemKey itemKey = inventory.getItemKeyInventory().getItemKey();
		if (lotInfo == null) {
			if (itemKey.getItem().getId()==item.getId()) {
				return true;
			}
		} else if(itemKey.getItem().getId()==item.getId() 
				&& (lotInfo.getPropC1()==null || 
						(lotInfo.getPropC1()!=null && lotInfo.getPropC1().equals(itemKey.getLotInfo().getPropC1())))
				&& (lotInfo.getPropC2()==null || 
						(lotInfo.getPropC2()!=null && lotInfo.getPropC2().equals(itemKey.getLotInfo().getPropC2())))
				&& (lotInfo.getPropC3()==null || 
						(lotInfo.getPropC3()!=null &&  lotInfo.getPropC3().equals(itemKey.getLotInfo().getPropC3())))
				&& (lotInfo.getPropC4()==null || 
						(lotInfo.getPropC4()!=null &&  lotInfo.getPropC4().equals(itemKey.getLotInfo().getPropC4())))
				&& (lotInfo.getPropC5()==null || 
						(lotInfo.getPropC5()!=null && lotInfo.getPropC5().equals(itemKey.getLotInfo().getPropC5())))
				&& (lotInfo.getPropC6()==null || 
						(lotInfo.getPropC6()!=null && lotInfo.getPropC6().equals(itemKey.getLotInfo().getPropC6())))
				&& (lotInfo.getPropC7()==null || 
						(lotInfo.getPropC7()!=null &&  lotInfo.getPropC7().equals(itemKey.getLotInfo().getPropC7())))
				&& (lotInfo.getPropC8()==null || 
						(lotInfo.getPropC8()!=null &&  lotInfo.getPropC8().equals(itemKey.getLotInfo().getPropC8())))
				&& (lotInfo.getPropC9()==null || 
						(lotInfo.getPropC9()!=null &&  lotInfo.getPropC9().equals(itemKey.getLotInfo().getPropC9())))
				&& (lotInfo.getPropN1()==0.0 || 
						(lotInfo.getPropN1()!=0.0 &&  lotInfo.getPropN1()==itemKey.getLotInfo().getPropN1()))
				&& (lotInfo.getPropN2()==0.0 || 
						(lotInfo.getPropN2()==0.0 &&  lotInfo.getPropN2()==itemKey.getLotInfo().getPropN2()))
				&& (lotInfo.getPropN3()==0.0 || 
						(lotInfo.getPropN3()==0.0 &&  lotInfo.getPropN3()==itemKey.getLotInfo().getPropN3()))
		        && (lotInfo.getPropD1()==null || 
						(lotInfo.getPropD1()!=null &&  lotInfo.getPropD1().equals(itemKey.getLotInfo().getPropD1())))
				&& (lotInfo.getPropD2()==null || 
						(lotInfo.getPropD2()!=null && lotInfo.getPropD2().equals(itemKey.getLotInfo().getPropD2())))
				&& (lotInfo.getPropD3()==null || 
						(lotInfo.getPropD3()!=null &&  lotInfo.getPropD3().equals(itemKey.getLotInfo().getPropD3())))
				&& (lotInfo.getPropL1()==null || 
						(lotInfo.getPropL1()!=null && lotInfo.getPropL1()==itemKey.getLotInfo().getPropL1()))
				&& (lotInfo.getPropL2()==null || 
						(lotInfo.getPropL2()!=null && lotInfo.getPropL2()==itemKey.getLotInfo().getPropL2()))
				&& (lotInfo.getPropL3()==null || 
						(lotInfo.getPropL3()!=null && lotInfo.getPropL3()==itemKey.getLotInfo().getPropL3()))
				){
			return true;
		}
		return false;
	}
	
//关闭-----------------------------------------------------------------------------------
	@SuppressWarnings("unchecked")
	public void close(List<Long> ids) {
		String barCode=null;
		List<ProcessDoc> processDocs = this.commonDao.loadAll(ProcessDoc.class,ids.toArray(new Long[ids.size()]));
		
		for (ProcessDoc processDoc : processDocs) {
			if (processDoc.getProcessQuantity() == 0) {
				continue;
			}
			
			//对已分配但未全部拣货加工作业Task的处理
			if(processDoc.getAllocatedQuantity()>processDoc.getPickedQuantity()){
				List<Task> tasks = this.commonDao.findByNamedQuery("getNotAllPickTasksByProcessDocId",
						new String[] { "processDocId" }, new Object[] { processDoc.getId() });
				List<Task> ts = new ArrayList<Task>();
				for (Task task : tasks) {
					double qty = task.getPlanQuantityMU() - task.getMovedQuantityMU();
					if (qty > 0) {
						task.unallocateProcessDoc(qty);
	    				ItemKeyInventory itemKeyInventory = inventoryManager.getItemKeyInventory(
	    						task.getSrcLoc().getWarehouse(), task.getItemKey());
	    				Inventory inventory = itemKeyInventory.getInventoryWithException(task.getSrcLoc(), task.getPackageUnit(), 
	    						task.getSrcLP(),barCode, task.getInventoryStatus(), task.getStorageDate(), task.getSOI());
	    				inventory.unallocate(qty, null, null);
					}
					if (task.getPlanQuantityMU()== 0) {
						ts.add(task);
					}
				}
				for(Task task : ts){
					task.getProcessDocBOMDetail().getTasks().remove(task);//删除task
				}
			}
			
			//删除预分配表中与该加工单关联的所有预分配记录
			commonDao.executeByNamed("deletePreAllocateByWarehouseAndCode", 
					new String[] {"code", "warehouseId"}, new Object[] {processDoc.getCode(), processDoc.getWarehouse().getId()});

			processDoc.setStatus(ProcessDocStatus.CLOSE);
			this.commonDao.store(processDoc);
		}
	}

	public void allocate(List<Long> ids){
		List<ProcessDoc> processDocs = this.commonDao.loadAll(ProcessDoc.class,ids.toArray(new Long[(ids.size())]));
		String errMsg = "";
		for (ProcessDoc doc : processDocs) {
			if (doc.getAbstractMoveDocDetails() != null&& doc.getAbstractMoveDocDetails().size() != 0) {
				if (preAllocate(doc)) {
					autoAllocator.allocate(null, null, null, doc.getAbstractMoveDocDetails());
					setProcessDocAllocateComponents(doc);
					errMsg+=doc.getCode()+" 加工单分配成功;";
				}else{
					errMsg+=doc.getCode()+" 加工单分配失败;";
				}
			}
		}
		LocalizedMessage.addLocalizedMessage(errMsg);
	}
	
	/**
	 * 对已分配的子明细拼成套数并写分配数量。
	 * @param item
	 * @return
	 */
	private void setProcessDocAllocateComponents(ProcessDoc processDoc) {
		Map<Long,Double> map = new HashMap<Long,Double>();
		for(ProcessDocDetail processDocDetail:processDoc.getDetails()){
			double quantity = -1;
			for (BOMComponent component : processDocDetail.getItem().getComponents()) {
				ProcessDocBOMDetail detail = processDoc.getProcessDocBOMDetailByItem(component.getComponent());
				double allocQty = detail.getAllocatedQuantity()-(map.get(detail.getId())==null?0:map.get(detail.getId()).doubleValue());
				if (quantity == -1) {
					quantity = ((Double) (allocQty / component.getQuantity())).intValue();
				} else {
					if (quantity > ((Double) (allocQty / component.getQuantity())).intValue()) {
						quantity = ((Double) (allocQty / component.getQuantity())).intValue();
					}
				}
			}
			double componentQty = processDocDetail.getQuantity()>quantity?quantity:processDocDetail.getQuantity();
			getBomDetailQuantityMap(map,processDocDetail,componentQty);
			processDoc.allocate(processDocDetail,componentQty);
		}
	}
	
	/**
	 * 拼成套件时子件明细已用映射
	 * @param map
	 * @param processDocDetail
	 * @param quantity
	 */
	private void getBomDetailQuantityMap(Map<Long,Double> map,ProcessDocDetail processDocDetail,double quantity){
		for (BOMComponent component : processDocDetail.getItem().getComponents()) {
			ProcessDocBOMDetail detail = processDocDetail.getProcessDoc().getProcessDocBOMDetailByItem(component.getComponent());
			Double d = map.get(detail.getId());
			if(d==null){
				map.put(detail.getId(),quantity*component.getQuantity());
			}else{
				d = Double.valueOf(d.doubleValue()+quantity);
			}
		}
	}
	
	public void unallocate(List<Long> ids) {
		List<ProcessDoc> processDocs = this.commonDao.loadAll(ProcessDoc.class,ids.toArray(new Long[(ids.size())]));
		for (ProcessDoc processDoc : processDocs) {
			autoAllocator.unallocate(processDoc);
			processDoc.unallocate();
			unPreAllocate(processDoc);
		}
	}
	
	/**
	 * 对加工作业单进行预分配
	 * @param processDoc
	 */
	private boolean preAllocate(ProcessDoc processDoc) {
		boolean flag = false;
		if (ProcessDocStatus.ACTIVE.equals(processDoc.getStatus())) {
			if (processDoc.getBomDetails() != null || processDoc.getBomDetails().size() > 0) {
				for(ProcessDocBOMDetail detail:processDoc.getBomDetails()){
					autoAllocator.preAllocate(detail,detail.getUnPreAllocateQuantity());
					if(detail.getPreAllocatedQuantity()>detail.getAllocatedQuantity()){
						flag = true;
					}
				}
			}
		}
		return flag;
	}

	
	/**
	 * 对加工作业单进行取消预分配
	 * @param processDoc
	 */
	private void unPreAllocate(ProcessDoc processDoc){
		if (processDoc.getBomDetails() != null|| processDoc.getBomDetails().size() > 0) {
			for (ProcessDocBOMDetail detail : processDoc.getBomDetails()) {
				autoAllocator.unPreAllocate(detail, detail.getUnallocateQuantity());
			}
		}
	}
	
	/**
	 * 加工单整单拣货
	 */
	@SuppressWarnings("unchecked")
	public void pickConfirmForPickAll(Long processDocId,Long workerId) {
		String hql = "select task from Task task where task.processDocBOMDetail.processDoc.id ="
				+ processDocId + " and (task.planQuantityMU -task.movedQuantityMU)>0 ";
		List<Task> tasks = commonDao.findByQuery(hql);
		for (Task task : tasks) {
			double qty = task.getPlanQuantityMU() - task.getMovedQuantityMU();
			if (qty > 0) {
				pickConfirm(task.getId(), qty, workerId);
			}
		}
	}
	
	/**
	 * 对加工单任务进行逐一拣货确认
	 */
	public void pickConfirm(Long taskId, double pickedQuantity, Long workerId) {
		Task task = commonDao.load(Task.class,taskId);
		String barCode=null;
		double qty = task.getPlanQuantityMU() - task.getMovedQuantityMU();
		if(qty < pickedQuantity){
			throw new BusinessException("pick.quantity.error");
		}
		
		//task.pickConfirm(task.getPackageUnit(), pickedQuantity, w);
		//库存移位处理
		ItemKeyInventory itemKeyInventory = inventoryManager.getItemKeyInventory(
				task.getSrcLoc().getWarehouse(), task.getItemKey());
		Inventory srcInv = itemKeyInventory.getInventory(task.getSrcLoc(), task.getPackageUnit(), 
				task.getSrcLP(),barCode,"",task.getStorageDate(),task.getSOI());
		if (srcInv != null) {
			//对源库存取消分配
	        srcInv.unallocate(pickedQuantity, null, null);
			//移位确认(捡货确认是将货物捡到月台上面,没有托盘)
			inventoryManager.moveInventory(srcInv.getId(), task.getDstLoc().getId(), null, pickedQuantity, task.getPackageUnit().getId(), task.getId(), workerId);
		} else {
			throw new BusinessException("move.inventory.none");
		}
		setProcessDocPickComponents(task.getProcessDocBOMDetail().getProcessDoc());
	}

	/**
	 * 单一任务拣货确认
	 */
	public void pickConfirm(Long taskId, Long srcLocId, String lp, String lot, Long packageUnitId,
			double pickedQuantity, Long workerId ) {
		String barCode=null;
		Task task = commonDao.load(Task.class,taskId);
		PackageUnit packageUnit =  commonDao.load(PackageUnit.class,packageUnitId);
		Location srcLocation = commonDao.load(Location.class, srcLocId);
		pickedQuantity = pickedQuantity * packageUnit.getConvertFigure();
		
		if((task.getPlanQuantityMU() - task.getMovedQuantityMU()) < pickedQuantity){
			throw new BusinessException("pick.quantity.error");
		}
		
		Stock srcLp = task.getSrcLP();//源托盘
		Stock dstLp = task.getDstLP() ;//目标托盘号
		ItemKey itemKey = task.getItemKey();
		//是否修改了批次
		if(StringUtils.isNotEmpty(lot) && !lot.equals(task.getItemKey().getLot())){
			itemKey = (ItemKey) commonDao.findByNamedQueryUniqueResult("getItemKeyByLot", 
					new String[] {"lot"}, new Object[] {lot});
			if(itemKey==null){
				throw new BusinessException("input.lot.error");
			}
		}

		//对源库存取消分配
		ItemKeyInventory srcItemKeyInventory = inventoryManager.getItemKeyInventory(
				task.getSrcLoc().getWarehouse(), task.getItemKey());	
		Inventory srcInv = srcItemKeyInventory.getInventory(task.getSrcLoc(), task.getPackageUnit(),
				task.getSrcLP(), barCode,task.getInventoryStatus(),task.getStorageDate(),task.getSOI());
		if (srcInv == null) {
			throw new BusinessException("move.inventory.none");
		}
        srcInv.unallocate(pickedQuantity, null, null);
        
        if (srcLocation.equals(task.getSrcLoc())
				&& ((srcLp==null&&task.getSrcLP()==null) || srcLp.equals(task.getSrcLP()))
				&& itemKey.equals(task.getItemKey())
				&& packageUnit.equals(task.getPackageUnit())) {
        	inventoryManager.moveInventory(srcInv.getId(), task.getDstLoc().getId(), 
        			dstLp == null ? null : dstLp.getId(), pickedQuantity, task.getPackageUnit().getId(), task.getId(), workerId);
        } else {
            //扣减实际拣货库位库存
            ItemKeyInventory actItemKeyInventory = inventoryManager.getItemKeyInventory(
            		srcLocation.getWarehouse(), itemKey);
            List<Inventory> invs = actItemKeyInventory.getInventories(srcLocation, srcLp, 
            		task.getStorageDate(), task.getSOI(), task.getInventoryStatus());
            double moveQty = 0;
            for (Inventory inv : invs) {
            	if (pickedQuantity > inv.getAvaliableQuantity()) {
                	moveQty = inv.getAvaliableQuantity();
            	} else {
            		moveQty = pickedQuantity;
            	}
            	inventoryManager.moveInventory(inv.getId(), task.getDstLoc().getId(), 
            			dstLp == null ? null : dstLp.getId(), moveQty, packageUnit.getId(), task.getId(), workerId);
            	pickedQuantity -= moveQty;
            	if (pickedQuantity <= 0) {
            		break;
            	}
            }
            
    		if (pickedQuantity > 0) {
    			throw new BusinessException("move.inventory.none");
    		}
        }
		//task.pickConfirm(itemKey, srcLocation, srcLp, task.getDstLoc(), dstLp,"",task.getStorageDate(),
		//		task.getSOI(), packageUnit, pickedQuantity, w);
		setProcessDocPickComponents(task.getProcessDocBOMDetail().getProcessDoc());
	}
	
	/**
	 * 对已分配的子明细拼成套数并写分配数量。
	 * @param item
	 * @return
	 */
	private void setProcessDocPickComponents(ProcessDoc processDoc) {
		Map<Long,Double> map = new HashMap<Long,Double>();
		for(ProcessDocDetail processDocDetail:processDoc.getDetails()){
			double quantity = -1;
			for (BOMComponent component : processDocDetail.getItem().getComponents()) {
				ProcessDocBOMDetail detail = processDoc.getProcessDocBOMDetailByItem(component.getComponent());
				double allocQty = detail.getPickedQuantity()-(map.get(detail.getId())==null?0:map.get(detail.getId()).doubleValue());
				if (quantity == -1) {
					quantity = ((Double) (allocQty / component.getQuantity())).intValue();
				} else {
					if (quantity > ((Double) (allocQty / component.getQuantity())).intValue()) {
						quantity = ((Double) (allocQty / component.getQuantity())).intValue();
					}
				}
			}
			double componentQty = processDocDetail.getQuantity()>quantity?quantity:processDocDetail.getQuantity();
			getBomDetailQuantityMap(map,processDocDetail,componentQty);
			processDoc.pick(processDocDetail,componentQty);
		}
	}
}
