package nc.impl.ic.onhand.service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;

import nc.bs.framework.common.NCLocator;
import nc.bs.ic.onhand.action.OnhandResBalance;
import nc.bs.ic.onhand.bp.OnhandBaseQry;
import nc.bs.ic.onhand.bp.OnhandDataFactory;
import nc.bs.ic.onhand.bp.OnhandLocationQry;
import nc.bs.ic.onhand.bp.OnhandSynQuery;
import nc.bs.ic.pub.env.ICBSContext;
import nc.impl.pubapp.bd.material.assistant.MarAssistantCheckUtils;
import nc.itf.ic.onhand.OnhandResService;
import nc.itf.scmpub.reference.uap.bd.customer.CustomerPubService;
import nc.itf.scmpub.reference.uap.bd.supplier.SupplierPubService;
import nc.pubitf.ic.reserve.ReserveInOut;
import nc.pubitf.uapbd.IMaterialPubService_C;
import nc.pubitf.uapbd.assistant.IMarAssistantPubService;
import nc.vo.bd.material.MaterialVO;
import nc.vo.bd.userdefrule.UserdefitemVO;
import nc.vo.ic.general.define.ICBillBodyVO;
import nc.vo.ic.general.define.ICBillHeadVO;
import nc.vo.ic.general.define.ICBillVO;
import nc.vo.ic.material.define.InvCalBodyVO;
import nc.vo.ic.onhand.define.ICBillOnhandReq;
import nc.vo.ic.onhand.define.ICBillPickResults;
import nc.vo.ic.onhand.define.OnhandBalanceResult;
import nc.vo.ic.onhand.entity.OnhandDimVO;
import nc.vo.ic.onhand.entity.OnhandVO;
import nc.vo.ic.onhand.pub.HashVOUtils;
import nc.vo.ic.onhand.pub.OnhandQueryDim;
import nc.vo.ic.onhand.pub.OnhandSelectDim;
import nc.vo.ic.onhand.pub.OnhandVOTools;
import nc.vo.ic.pub.define.ICPubMetaNameConst;
import nc.vo.ic.pub.util.CollectionUtils;
import nc.vo.ic.pub.util.DimMatchedObj;
import nc.vo.ic.pub.util.NCBaseTypeUtils;
import nc.vo.ic.pub.util.StringUtil;
import nc.vo.ic.pub.util.VOEntityUtil;
import nc.vo.ic.pub.util.ValueCheckUtil;
import nc.vo.pub.AggregatedValueObject;
import nc.vo.pub.BusinessException;
import nc.vo.pub.ISuperVO;
import nc.vo.pub.lang.UFDate;
import nc.vo.pub.lang.UFDateTime;
import nc.vo.pub.lang.UFDouble;
import nc.vo.pubapp.AppContext;
import nc.vo.pubapp.pattern.exception.ExceptionUtils;
import nc.vo.pubapp.pattern.pub.MapList;
import nc.vo.pubapp.pattern.pub.MathTool;
import nc.vo.sc.m61.entity.SCOrderIssueVO;
import nc.vo.scmpub.res.billtype.ICBillType;

/**
 * <p>
 * <b>结存资源服务</b>
 *
 * @version v60
 * @since v60
 * @author yangb
 * @time 2010-4-15 下午10:14:36
 */
public class OnhandResServiceImpl implements OnhandResService {

    /**
     * OnhandResServiceImpl 的构造子
     */
    public OnhandResServiceImpl() {
        // 默认构造
    }

    @Override
    public SCOrderIssueVO[] getSCOrderIssueVOs(AggregatedValueObject[] billvos)
            throws BusinessException {
        if (ValueCheckUtil.isNullORZeroLength(billvos)) {
            return null;
        }
        try {
            return OnhandDataFactory.getOnhandDataSource(billvos[0])
                    .getSCOrderIssueVOs(billvos);
        }
        catch (Exception e) {
            ExceptionUtils.marsh(e);
        }
        return null;
    }

    @Override
    public ICBillPickResults pickAuto(ICBillVO billvo) throws BusinessException {
        return this.pickAuto(billvo, true);
    }

    /**
     * 自动拣货
     * @param billvo 单据vo
     * @param pickNumNotNull 实发数量不为零的行是否需要重新拣货
     * @return
     * @throws BusinessException
     */
    public ICBillPickResults pickAuto(ICBillVO billvo, boolean pickNumNotNull) throws BusinessException {
        try {
            List<OnhandBalanceResult<ICBillOnhandReq>> retults =
                    this.pickAutoInner(new ICBillVO[] {
                            billvo
                    }, pickNumNotNull);
            if (retults == null || retults.size() <= 0) {
                return null;
            }
            if(retults.get(0).isResPick()) {
                return null;
            }
            ICBillPickResults ret = new ICBillPickResults(retults, billvo.getBodys());
            ret.getPickBodys();
            return ret;
        }
        catch (Exception e) {
            ExceptionUtils.marsh(e);
        }
        return null;
    }

    /**
     *
     */
    @Override
    public ICBillVO[] pickAuto(ICBillVO[] bills) throws BusinessException {
        return this.pickAuto(bills, true);
    }

    /**
     * 自动拣货考虑预留的情况需要控制预留的行需不需要重新拣货，这块加一个开关
     * modify by yangls7 for hwpoc
     * @param bills
     * @param pickNumNotNull 是否重新捡实发数量不为0的行
     * @return
     * @throws BusinessException
     */
    public ICBillVO[] pickAuto(ICBillVO[] bills, boolean pickNumNotNull) throws BusinessException {
        for(ICBillVO billvo : bills) {
            ICBillBodyVO[] bodyvos = billvo.getBodys();
            for (int i = 0; i < bodyvos.length; i++) {
                bodyvos[i].setAttributeValue(ICPubMetaNameConst.NNUM, null);
                bodyvos[i].setAttributeValue(ICPubMetaNameConst.NASSISTNUM, null);
                bodyvos[i].setAttributeValue(ICPubMetaNameConst.VNOTEBODY, null);
            }
        }
        // 处理预留拣货
        NCLocator.getInstance().lookup(ReserveInOut.class)
                .reserveOutAutoPick(bills, false);

        List<OnhandBalanceResult<ICBillOnhandReq>> retults =
                this.pickAutoInner(bills, pickNumNotNull);
//    if (retults == null || retults.size() <= 0) {
//      return bills;
//    }
        try {
            List<ICBillBodyVO> lbodys = new ArrayList<ICBillBodyVO>();
            for (ICBillVO bill : bills) {
                ICBillBodyVO[] bodys = bill.getBodys();
                if (ValueCheckUtil.isNullORZeroLength(bodys)) {
                    continue;
                }
                for (ICBillBodyVO body : bodys) {
                    lbodys.add(body);
                }
            }
            ICBillPickResults ret =
                    new ICBillPickResults(retults, lbodys.toArray(new ICBillBodyVO[lbodys
                            .size()]));

            ICBillBodyVO[] pickbodys = ret.getPickBodys();
            MapList<Integer, ICBillBodyVO> mapPickBodyVOs =
                    new MapList<Integer, ICBillBodyVO>();
            //根据供应商 客户oid 日期 设置vid的值
            HashSet<String> cvendoridset = new HashSet<String>();
            HashSet<String> casscustidset = new HashSet<String>();
            // 货主客户
            HashSet<String> ctplcustomeridset = new HashSet<String>();
            // 寄存供应商
            HashSet<String> cvmivenderidset = new HashSet<String>();
            for (ICBillBodyVO body : pickbodys) {
                String cvendorid = body.getCvendorid();
                String casscustid = body.getCasscustid();
                String ctplcustomerid = body.getCtplcustomerid();
                String cvmivenderid = body.getCvmivenderid();
                if (cvendorid != null) {
                    cvendoridset.add(cvendorid);
                }
                if (casscustid != null) {
                    casscustidset.add(casscustid);
                }
                if (ctplcustomerid != null) {
                    ctplcustomeridset.add(ctplcustomerid);
                }
                if (cvmivenderid != null) {
                    cvmivenderidset.add(cvmivenderid);
                }

            }
            // 获取所有表体的供应商oid 拣货后台逻辑未变只带出物料辅助属性的客户 供应商oid 补充vid
            HashMap<String, String> cvendoridMap = new HashMap<String, String>();
            HashMap<String, String> casscustidMap = new HashMap<String, String>();
            HashMap<String, String> ctplcustomeridMap = new HashMap<String, String>();
            HashMap<String, String> cvmivenderidMap = new HashMap<String, String>();
            HashMap<String, UFDate>  cvendoridAndDate= new HashMap<String, UFDate>();
            HashMap<String, UFDate>  casscustidAndDate= new HashMap<String, UFDate>();
            HashMap<String, UFDate> ctplcustomeridAndDate = new HashMap<String, UFDate>();
            HashMap<String, UFDate> cvmivenderidAndDate = new HashMap<String, UFDate>();
            UFDate busidate = AppContext.getInstance().getBusiDate();
            if (cvendoridset != null && cvendoridset.size() > 0) {
                for(String cvendorid : cvendoridset) {
                    cvendoridAndDate.put(cvendorid,busidate);
                }
                //根据供应商oid和业务日期查询vid
                cvendoridMap = (HashMap<String, String>) SupplierPubService.querySupplierVidsByOidAndDate(cvendoridAndDate);
            }
            if (casscustidset != null && casscustidset.size() > 0) {
                for(String casscustid : casscustidset) {
                    casscustidAndDate.put(casscustid,busidate);
                }
                //根据客户oid和业务日期查询vid
                casscustidMap = (HashMap<String, String>) CustomerPubService.queryCustomerVidsByOidsAndDate(casscustidAndDate);
            }
            if (ctplcustomeridset != null && ctplcustomeridset.size() > 0) {
                for (String ctplcustomerid : ctplcustomeridset) {
                    ctplcustomeridAndDate.put(ctplcustomerid, busidate);
                }
                // 根据货主客户oid和业务日期查询vid
                ctplcustomeridMap = (HashMap<String, String>) CustomerPubService
                        .queryCustomerVidsByOidsAndDate(ctplcustomeridAndDate);
            }
            if (cvmivenderidset != null && cvmivenderidset.size() > 0) {
                for (String cvmivenderid : cvmivenderidset) {
                    cvmivenderidAndDate.put(cvmivenderid, busidate);
                }
                // 根据寄存供应商oid和业务日期查询vid
                cvmivenderidMap = (HashMap<String, String>) SupplierPubService
                        .querySupplierVidsByOidAndDate(cvmivenderidAndDate);
            }
            //根据客户 供应商oid对vid赋值
            for (ICBillBodyVO body : pickbodys) {
                if (body.getCvendorid() != null) {
                    body.setCvendorvid(cvendoridMap.get(body.getCvendorid()));
                }
                if (body.getCasscustid() != null) {
                    body.setCasscustvid(casscustidMap.get(body.getCasscustid()));
                }
                if (body.getCtplcustomerid() != null) {
                    body.setCtplcustomervid(ctplcustomeridMap.get(body.getCtplcustomerid()));
                }
                if (body.getCvmivenderid() != null) {
                    body.setCvmivendervid(cvmivenderidMap.get(body.getCvmivenderid()));
                }
            }
            for (ICBillBodyVO pickbody : pickbodys) {
                mapPickBodyVOs.put(pickbody.getPseudoColumn(), pickbody);
            }
            for (ICBillVO bill : bills) {
                lbodys = mapPickBodyVOs.get(bill.getHead().getPseudoColumn());
                if (ValueCheckUtil.isNullORZeroLength(lbodys)) {
                    continue;
                }
                bill.setChildrenVO(CollectionUtils.listToArray(lbodys));
                // 记录拣货标识
                bill.getHead().setAttributeValue("ispickauto", "Y");
            }
            // 新增预留拣货，需要处理行备注
            for(ICBillVO bill : bills) {
                for(ICBillBodyVO bodyVO : bill.getBodys()) {
                    if(MathTool.equals(bodyVO.getNnum(), bodyVO.getNshouldnum())) {
                        bodyVO.setVnotebody(null);
                    }
                }
            }
            return bills;
        }
        catch (Exception e) {
            ExceptionUtils.marsh(e);
        }
        return bills;
    }

    /**
     * 方法功能描述：查询单据的现存量(自动主辅计量平衡使用，过滤非自动主辅计量平衡物料)
     * <p>
     * 非严格匹配的查询，只用非空维度字段做过滤 <b>默认查询所有维度字段，不做汇总处理，包括可用和不可用的结存</b>
     *
     * @param bills 查询维度
     * @since 6.0
     * @author yangb
     * @time 2010-7-8 下午09:18:24
     */
    @Override
    public OnhandVO[] queryOnhandVOByBills(ICBillVO[] bills)
            throws BusinessException {
        try {
            List<OnhandDimVO> ldimvos =
                    OnhandVOTools.getOnhandDimVOs(bills, new ICBSContext().getInvInfo());
            if (ValueCheckUtil.isNullORZeroLength(ldimvos)) {
                return null;
            }
            ICBSContext context = new ICBSContext();
            OnhandDimVO[] dimvos = ldimvos.toArray(new OnhandDimVO[ldimvos.size()]);
            OnhandVOTools.getRealOnhandDim(context.getInvInfo(), dimvos);
            InvCalBodyVO[] invCalVOs =
                    context.getInvInfo().getInvCalBodyVO(
                            VOEntityUtil.getVOsValues(dimvos, OnhandDimVO.PK_ORG,
                                    String.class),
                            VOEntityUtil.getVOsValues(dimvos, OnhandDimVO.CMATERIALVID,
                                    String.class));
            List<OnhandDimVO> lbalancevos = new ArrayList<OnhandDimVO>();
            Set<String> keysset = new HashSet<String>();
            String key = null;
            for (int i = 0; i < dimvos.length; i++) {
                if (!ValueCheckUtil.isTrue(invCalVOs[i].getAutobalancemeas())) {
                    continue;
                }
                key = HashVOUtils.getContentKey(dimvos[i]);
                if (keysset.contains(key)) {
                    continue;
                }
                lbalancevos.add(dimvos[i]);
            }
            if (ValueCheckUtil.isNullORZeroLength(lbalancevos)) {
                return null;
            }
            return this.queryOnhandVOByDims(lbalancevos
                    .toArray(new OnhandDimVO[lbalancevos.size()]));
        }
        catch (Exception e) {
            ExceptionUtils.marsh(e);
        }
        return null;
    }

    /**
     * 方法功能描述：查询现存量
     * <p>
     * 非严格匹配的查询，只用非空维度字段做过滤 <b>默认查询所有维度字段，不做汇总处理，包括可用和不可用的结存</b>
     *
     * @param dimvos 查询维度
     * @since 6.0
     * @author yangb
     * @time 2010-7-8 下午09:18:24
     */
    @Override
    public OnhandVO[] queryOnhandVOByDims(OnhandDimVO[] dimvos)
            throws BusinessException {
        try {
            OnhandSelectDim select = new OnhandSelectDim();
            select.setSum(false);
            select.addSelectFields(CollectionUtils.combineArrs(
                    OnhandDimVO.getDimContentFields(), new String[] {
                            OnhandDimVO.PK_ONHANDDIM, OnhandDimVO.VHASHCODE,
                            OnhandDimVO.VSUBHASHCODE
                    }));
            return this.queryOnhandVOByDims(select, dimvos, false, null);
        }
        catch (Exception e) {
            ExceptionUtils.marsh(e);
        }
        return null;
    }

    @Override
    public OnhandVO[] queryOnhandVOByDims(OnhandSelectDim select,
                                          OnhandDimVO[] dimvos, boolean bqueryuseablestate, String bytranstype)
            throws BusinessException {
        try {
            List<String> ltranstypes = null;
            if (bytranstype != null) {
                ltranstypes = new ArrayList<String>();
                ltranstypes.add(bytranstype);
            }
            return new OnhandBaseQry().queryOnhandVOByDims(select, dimvos,
                    bqueryuseablestate, ltranstypes);
        }
        catch (Exception e) {
            ExceptionUtils.marsh(e);
        }
        return null;
    }

    /**
     * 方法功能描述：根据现存量维度查询可用的存量（为预留提供） 仅仅查询库存状态可用的存量
     *
     * @author yangb
     * @time 2010-6-5 下午10:43:05
     */
    @Override
    public OnhandVO[] queryUseableOnhand(OnhandDimVO[] dimvos)
            throws BusinessException {
        if (ValueCheckUtil.isNullORZeroLength(dimvos)) {
            return null;
        }
        try {
            OnhandSelectDim select = new OnhandSelectDim();
            select.setSum(false);
            select.addSelectFields(CollectionUtils.combineArrs(
                    OnhandDimVO.getDimContentFields(), new String[] {
                            OnhandDimVO.PK_ONHANDDIM, OnhandDimVO.VHASHCODE,
                            OnhandDimVO.VSUBHASHCODE
                    }));
            return this.queryOnhandVOByDims(select, dimvos, true, null);
        }
        catch (Exception e) {
            ExceptionUtils.marsh(e);
        }
        return null;
    }

    /**
     * 方法功能描述：根据现存量维度查询可用的存量（为可用量提供） 仅仅查询库存状态可用的存量
     * 未除去不影响可用量的仓库
     *
     * @author yangb
     * @time 2010-6-5 下午10:43:05
     */
    @Override
    public OnhandVO[] queryUseableOnhandForAtp(OnhandDimVO[] dimvos)
            throws BusinessException {
        try {
            return new OnhandBaseQry().queryOnhandVOByDims(null, dimvos, true, null);
        }
        catch (Exception e) {
            ExceptionUtils.marsh(e);
        }
        return null;
    }



    /**
     *
     * @param billvos
     * @param pickNumNotNull 实发数量不为0的行是否需要重新拣货
     * @return
     */
    private List<OnhandBalanceResult<ICBillOnhandReq>> pickAutoInner(
            ICBillVO[] billvos, boolean pickNumNotNull) {
        if (ValueCheckUtil.isNullORZeroLength(billvos)) {
            return null;
        }
        //对于物料辅助属性设置了boolean值且未启用  默认值是N 所以此处先进行清空处理 置为null
        IMarAssistantPubService assistantPubService = NCLocator.getInstance().lookup(IMarAssistantPubService.class);
        try {
            UserdefitemVO[] userdefitemVOs = assistantPubService.queryMarAssistantDefine(AppContext.getInstance().getPkGroup());
            boolean isUseDef = false;
            if(userdefitemVOs!=null) {
                for (UserdefitemVO vo : userdefitemVOs) {
                    if(vo.getClassid().equals("BS000010000100001032")) {
                        isUseDef = true;
                    }
                }
            }
            if (isUseDef) {
                this.processFreeDef(billvos);
            }
        } catch (BusinessException e) {
            ExceptionUtils.wrappException(e);
        }
        List<String> ltranstypes = new ArrayList<String>();
        List<ICBillOnhandReq> lreqs = new ArrayList<ICBillOnhandReq>();
        int count = 0, totalrownum = 0;
        Integer billno = null;
        for (ICBillVO billvo : billvos) {
            ICBillBodyVO[] bodys = billvo.getBodys();
            ICBillHeadVO head = billvo.getHead();
            ICBillOnhandReq req = null;
            billno = Integer.valueOf(count);
            head.setPseudoColumn(billno);
            for (int i = 0; i < bodys.length; i++) {
                bodys[i].setPseudoColumn(billno);
                // 支持录入实发数量拣货
                // 填写了实发的则不捡货, 红字单据拣货和v57保持一致
                // 预留拣货在捡之前已经把实发置空，这块不需要再捡了  modify by yangls7 for hwpoc
                if (pickNumNotNull && (!NCBaseTypeUtils.isNullOrZero(bodys[i].getNnum())
                        || !NCBaseTypeUtils.isNullOrZero(bodys[i].getNassistnum()))) {
                    // 不拣货也需要自动加1，否则既有实发和应发行的时候，会串行（委外材料核销）
                    totalrownum++;
                    continue;
                }
                if (MathTool.compareTo(bodys[i].getNshouldnum(), UFDouble.ZERO_DBL) < 0
                        && MathTool.compareTo(bodys[i].getNshouldassistnum(),
                        UFDouble.ZERO_DBL) < 0) {
                    totalrownum++;
                    continue;
                }
                bodys[i].setPk_group(head.getPk_group());
                bodys[i].setPk_org(head.getPk_org());
                bodys[i].setPk_org_v(head.getPk_org_v());
                bodys[i].setCbodywarehouseid(head.getCwarehouseid());
                req = new ICBillOnhandReq(bodys[i]);
                req.setRowno(String.valueOf(totalrownum));
                totalrownum++;
                lreqs.add(req);
                if (!StringUtil.isSEmptyOrNull(head.getVtrantypecode())) {
                    ltranstypes.add(head.getVtrantypecode());
                }
            }
            count++;
        }
        List<OnhandBalanceResult<ICBillOnhandReq>> results =
                new ArrayList<OnhandBalanceResult<ICBillOnhandReq>>();
        if (ValueCheckUtil.isNullORZeroLength(lreqs)) {
            results.add(new OnhandBalanceResult<ICBillOnhandReq>(true));
            return results;
        }
        ICBillOnhandReq[] reqs = new ICBillOnhandReq[lreqs.size()];
        reqs = lreqs.toArray(reqs);
        OnhandResBalance<ICBillOnhandReq> resb =
                new OnhandResBalance<ICBillOnhandReq>(reqs);
        resb.setCtranstype(ltranstypes);

        resb.onhandBalance();
        OnhandBalanceResult<ICBillOnhandReq> result = null;
        for (ICBillOnhandReq reqq : reqs) {
            result = resb.getResults(reqq);
            if (result != null) {
                results.add(result);
            }
        }
        return results;
    }

    private void processFreeDef(ICBillVO[] billvos) {
        ICBillVO billvo = billvos[0];
        MapList<String, String> checkvalue = check(ICPubMetaNameConst.CMATERIALVID, billvo.getBodys());
        for (ICBillBodyVO bodyvo : billvo.getBodys()) {
            if (checkvalue == null) {
                for (int k = 1; k <= 10; k++) {
                    String index = "vfree" + k;
                    Object vfree = bodyvo.getAttributeValue(index);
                    if ((vfree != null && (vfree.equals("N") || vfree.equals("false"))) ) {
                        bodyvo.setAttributeValue(index, null);
                    }
                }
            } else {
                Map<String, List<String>> maplist = checkvalue.toMap();
                List<String> list = maplist.get(bodyvo.getAttributeValue(ICPubMetaNameConst.CMATERIALVID));
                for (int k = 1; k <= 10; k++) {
                    String index = "vfree" + k;
                    Object vfree = bodyvo.getAttributeValue(index);
                    if ((vfree != null && (vfree.equals("N") || vfree.equals("false")))) {
                        if(list==null || !list.contains(index)) {
                            bodyvo.setAttributeValue(index, null);
                        }
                    }
                }
            }
        }
    }

    public MapList<String, String> check(String materialField,ISuperVO[] valueObjects) {
        MapList<String, String> materialMapList = new MapList<String, String>();
        Map<String, MaterialVO> materialMap = this.getMaterialMap(materialField, valueObjects);//<pk,materialVo>
        if (materialMap == null || materialMap.size() == 0) {
            return null;
        }
        Map<String, List<Integer>> marFrameMap = this.getMarFrameMap(materialMap);
        if (marFrameMap == null || marFrameMap.size() == 0) {
            return null;
        }
        for (ISuperVO value : valueObjects) {
            Object pk_material = value.getAttributeValue(materialField);
            String pk_marasstframe = materialMap.get(pk_material).getPk_marasstframe();
            List<Integer> list = marFrameMap.get(pk_marasstframe);
            if(list==null) {
                continue;
            }
            for(Integer listvlaue:list) {
                if (pk_marasstframe != null) {
                    materialMapList.put(pk_material.toString(), "vfree"+(listvlaue-5));
                }
            }
        }
        return  materialMapList;
    }
    private Map<String, List<Integer>> getMarFrameMap(Map<String, MaterialVO> materialMap) {
        Map<String, List<Integer>> marFrameMap = null;
        try {
            Set<String> marFramePkSet = new HashSet<String>();
            for (Entry<String, MaterialVO> entry : materialMap.entrySet()) {
                String pk_marasstframe = entry.getValue().getPk_marasstframe();
                if (pk_marasstframe != null) {
                    marFramePkSet.add(pk_marasstframe);
                }
            }
            marFrameMap =
                    MarAssistantCheckUtils.queryMarAsstFrameIncludeDefPropIndex(marFramePkSet
                            .toArray(new String[0]));
        } catch (BusinessException e) {
            ExceptionUtils.wrappException(e);
        }
        return marFrameMap;
    }

    private Map<String, MaterialVO> getMaterialMap(String materialField, ISuperVO[] valueObjects) {
        Map<String, MaterialVO> materialMap = null;
        try {
            Set<String> marPkSet = new HashSet<String>();
            for (int i = 0; i < valueObjects.length; i++) {
                String pk_material = (String) valueObjects[i].getAttributeValue(materialField);
                marPkSet.add(pk_material);
            }

            IMaterialPubService_C marService =
                    NCLocator.getInstance().lookup(IMaterialPubService_C.class);
            materialMap =
                    marService.queryMaterialBaseInfoByPks(marPkSet.toArray(new String[0]), new String[] {
                            MaterialVO.PK_MARASSTFRAME, MaterialVO.NAME, MaterialVO.NAME2, MaterialVO.NAME3,
                            MaterialVO.NAME4, MaterialVO.NAME5, MaterialVO.NAME6});
        } catch (BusinessException e) {
            ExceptionUtils.wrappException(e);
        }
        return materialMap;
    }

    @Override
    public Map<String, String> queryLastInLocation(String pk_calbody,
                                                   String cwarehouseid, String[] cmaterialvids) throws BusinessException {
        try {
            return new OnhandLocationQry().queryLastInLocation(pk_calbody,
                    cwarehouseid, cmaterialvids);
        }
        catch (Exception ex) {
            ExceptionUtils.marsh(ex);
            return new HashMap<String, String>();
        }

    }

    @Override
    public Map<String, String> queryOnhandLocation(String pk_calbody,
                                                   String cwarehouseid, String[] cmaterialvids) throws BusinessException {
        try {
            return new OnhandLocationQry().queryOnhandLocation(pk_calbody,
                    cwarehouseid, cmaterialvids);
        }
        catch (Exception ex) {
            ExceptionUtils.marsh(ex);
            return new HashMap<String, String>();
        }
    }

    @Override
    public OnhandVO[] queryAtpOnhand(OnhandDimVO[] dimvos, boolean bextendWarehouse)
            throws BusinessException {
        try {
            return new OnhandSynQuery().queryOnhandForAtp(null, getQueryDim(dimvos),
                    bextendWarehouse);
        }
        catch (Exception e) {
            ExceptionUtils.marsh(e);
        }
        return new OnhandVO[0];
    }

    private OnhandQueryDim[] getQueryDim(OnhandDimVO[] dimvos) {
        if (ValueCheckUtil.isNullORZeroLength(dimvos)) {
            return null;
        }
        DimMatchedObj<OnhandDimVO> handkey = null;
        OnhandQueryDim[] dimconds = new OnhandQueryDim[dimvos.length];
        for (int i = 0; i < dimvos.length; i++) {
            handkey =
                    new DimMatchedObj<OnhandDimVO>(dimvos[i],
                            OnhandDimVO.getDimContentFields());
            dimconds[i] = new OnhandQueryDim();
            dimconds[i].addDimCondition(handkey.getDimFields(),
                    VOEntityUtil.getVOValues(dimvos[i], handkey.getDimFields()));
        }
        return dimconds;
    }

    @Override
    public OnhandVO[] queryAtpOnhandUP(OnhandDimVO[] dimvos,
                                       UFDateTime tupdatetime, UFDateTime endtime, boolean bextendWarehouse) throws BusinessException {
        return new OnhandSynQuery().queryOnhandForAtpUP(null,
                this.getQueryDim(dimvos), tupdatetime, endtime, bextendWarehouse);
    }

    @Override
    public ICBillPickResults reservePickAuto(ICBillVO[] billvos)
            throws BusinessException {
        //将实发数量清空
        this.cleanBodyNum(billvos);
        //处理预留，预留拣货出来的后续不会再拣货了
        billvos = this.processReserve(billvos);
        return this.pickAuto(billvos[0], false);
    }

    /**
     * 处理预留
     * @param vos
     * @return
     */
    private ICBillVO[] processReserve(ICBillVO[] vos) {
        if (ICBillType.GeneralOut.getCode().equals(
                (vos[0].getHead().getBillType().getCode()))) {
            return vos;
        }
        try {
            // 预留处理
            ICBillVO[] retvos = NCLocator.getInstance().lookup(ReserveInOut.class)
                    .reserveOutAutoPick(vos, false);
            return retvos;
        }
        catch (Exception e) {
            ExceptionUtils.wrappException(e);
        }
        return null;
    }

    /**
     * 清空表体的实发数量，实发主数量
     * @param vos
     * @return
     */
    private void cleanBodyNum(ICBillVO[] vos) {
        for(ICBillVO vo : vos) {
            for(ICBillBodyVO bodyVO : vo.getBodys()) {
                bodyVO.setNnum(null);
                bodyVO.setNassistnum(null);
                bodyVO.setVnotebody(null);
            }
        }
    }


}
