package nc.bs.pu.m21.maintain.rule.save;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import nc.bs.framework.common.NCLocator;
import nc.impl.pubapp.pattern.database.DataAccessUtils;
import nc.impl.pubapp.pattern.database.IDExQueryBuilder;
import nc.impl.pubapp.pattern.rule.IRule;
import nc.itf.pu.m21.IOrderSupplierQuery;
import nc.itf.pu.pub.IPURemoteCallCombinator;
import nc.itf.pubbd.profitcenter.IProfitCenterPubService;
import nc.itf.scmpub.reference.uap.bd.addrdoc.AddrdocPubService;
import nc.itf.scmpub.reference.uap.bd.currency.CurrencyRatePubService;
import nc.itf.scmpub.reference.uap.bd.customer.CustomerPubService;
import nc.itf.scmpub.reference.uap.bd.material.MaterialPubService;
import nc.itf.scmpub.reference.uap.bd.payment.PaymentService;
import nc.itf.scmpub.reference.uap.bd.psn.PsndocPubService;
import nc.itf.scmpub.reference.uap.bd.supplier.SupplierPubService;
import nc.itf.scmpub.reference.uap.bd.vat.BuySellFlagEnum;
import nc.itf.scmpub.reference.uap.org.OrgUnitPubService;
import nc.itf.scmpub.reference.uap.org.ProfitCenterPubService;
import nc.itf.scmpub.reference.uap.pf.PfServiceScmUtil;
import nc.itf.uap.pf.IPFConfig;
import nc.pubitf.org.IDeptPubService;
import nc.pubitf.uapbd.IMaterialPubService;
import nc.vo.bd.material.MaterialConvertVO;
import nc.vo.bd.material.MaterialVO;
import nc.vo.bd.payment.PaymentChVO;
import nc.vo.bd.payment.PaymentVO;
import nc.vo.bd.rate.util.RateReturnObject;
import nc.vo.profitcenter.ProfitCenterVO;
import nc.vo.pu.m21.entity.OrderHeaderVO;
import nc.vo.pu.m21.entity.OrderItemVO;
import nc.vo.pu.m21.entity.OrderPaymentVO;
import nc.vo.pu.m21.entity.OrderVO;
import nc.vo.pu.m21.enumeration.EnumBillStatus;
import nc.vo.pu.m21.pub.TrantypeUtil;
import nc.vo.pu.m21.query.supplier.SupplierInfo;
import nc.vo.pu.m21.rule.CurrencyAndExchangerate;
import nc.vo.pu.m21.rule.FlowStockOrgValue;
import nc.vo.pu.m21.rule.OrderScaleRule;
import nc.vo.pu.m21.rule.OrganizationDefaultValue;
import nc.vo.pu.m21.rule.PlanArriveDate;
import nc.vo.pu.m21.rule.ReqCorpDefaultValue;
import nc.vo.pu.m21.rule.vat.OrderVatValueFillRule;
import nc.vo.pu.m21.rule.vat.OrderVatValueFillRule.ICountrySetter;
import nc.vo.pu.m21.rule.vat.setter.country.OrderReceiveCountrySetter;
import nc.vo.pu.m21.rule.vat.setter.country.OrderSendCountrySetter;
import nc.vo.pu.m21.rule.vat.setter.country.OrderTaxCountrySetter;
import nc.vo.pu.pub.constant.PUParaValue;
import nc.vo.pu.pub.constant.PUTempTable;
import nc.vo.pu.pub.enumeration.EnumDiscounttaxtype;
import nc.vo.pu.pub.enumeration.POEnumBillStatus;
import nc.vo.pu.pub.enumeration.PricePriority;
import nc.vo.pu.pub.rule.WeightVolumePieceCalc;
import nc.vo.pu.pub.util.BillHelper;
import nc.vo.pu.pub.util.IKeyValue;
import nc.vo.pu.pub.util.PUSysParamUtil;
import nc.vo.pu.pub.util.PubSysParamUtil;
import nc.vo.pub.BusinessException;
import nc.vo.pub.CircularlyAccessibleValueObject;
import nc.vo.pub.SuperVO;
import nc.vo.pub.VOStatus;
import nc.vo.pub.lang.UFBoolean;
import nc.vo.pub.lang.UFDate;
import nc.vo.pub.lang.UFDouble;
import nc.vo.pub.lang.UFLiteralDate;
import nc.vo.pubapp.AppContext;
import nc.vo.pubapp.calculator.Calculator;
import nc.vo.pubapp.calculator.CalculatorUtil;
import nc.vo.pubapp.calculator.Condition;
import nc.vo.pubapp.calculator.HslParseUtil;
import nc.vo.pubapp.calculator.data.IDataSetForCal;
import nc.vo.pubapp.calculator.data.IRelationForItems;
import nc.vo.pubapp.calculator.data.RelationItemForCal;
import nc.vo.pubapp.calculator.data.VODataSetForCal;
import nc.vo.pubapp.pattern.data.IRowSet;
import nc.vo.pubapp.pattern.exception.ExceptionUtils;
import nc.vo.pubapp.pattern.pub.PubAppTool;
import nc.vo.pubapp.pattern.pub.SqlBuilder;
import nc.vo.pubapp.scale.BillVOScaleProcessor;
import nc.vo.pubapp.scale.ScaleUtils;
import nc.vo.pubapp.scale.TotalValueVOScaleProcessor;
import nc.vo.ratetype.RateTypeConstant;
import nc.vo.scmpub.res.billtype.POBillType;
import nc.vo.scmpub.res.para.NCPara;
import nc.vo.scmpub.util.StringUtil;
import nccloud.commons.collections.CollectionUtils;
import nccloud.commons.lang.ArrayUtils;
import nccloud.pubimpl.pu.m21.afterevent.service.body.TaxCode;

/**
 * @description 补全导入的数据
 * @author zhangmimi
 * @date 2021年12月9日 上午10:28:53
 * @version ncc1.0
 */
public class FillOrderVosRule implements IRule<OrderVO> {

	private ScaleUtils scaleUtils = null;
	private Map<String, IPURemoteCallCombinator> remoteCaller = new HashMap<String, IPURemoteCallCombinator>();
	private static final String VCHANGERATE = "1/1";

	@Override
	public void process(OrderVO[] vos) {
		String pk_group = vos[0].getHVO().getPk_group();
		this.scaleUtils = new ScaleUtils(pk_group);
		try {
			this.fillHeadVo(vos);
			this.fillBodyVo(vos);

			// 补充完数据信息之后做精度处理
			BillVOScaleProcessor scale = new BillVOScaleProcessor(pk_group, vos);
			TotalValueVOScaleProcessor totalScale = new TotalValueVOScaleProcessor(vos);
			new OrderScaleRule().setScale(scale, totalScale);
		} catch (BusinessException e) {
			ExceptionUtils.wrappException(e);
		}
	}

	/**
	 *
	 * 补充表体VO 1、表头退货标志为Y，导入时则校验表体数量金额是否为负，若不是，则提示“退货订单，数量不允许为正” 2.表头付款协议字段有值，导入时
	 * 创建表体付款协议数据 3.表头整单税率若有值，表体未设置税率字段，则表体获取标题得税率值 4.表头整单扣税类别有值，标题未设置，获取表头得值
	 * 5.表头币种与表体币种一致时，折本汇率字段为1，组织汇率类型、组织汇率来源日期为空
	 * 6.折扣为空时（折扣规则编码未导入），默认100%；折扣规则编码导入，根据编码反算折扣
	 * 7.需求部门pk_reqdept_v不为空，pk_reqdept为空，需要根据pk_reqdept_v填充pk_reqdept
	 *
	 * 物料materials 物料(VID) -》单位、主单位 客户 casscustvids (VID) -> 客户Oid
	 * 收货库存组织\物流组织\需求公司\收货利润中心\需求库存组织、结算采购组织、 arrvstoorgs(VID) ->收货库存组织OID 应付组织
	 * VID-》应付组织OID、结算利润中心 结算利润中心为空，则取应付组织对应的利润中心 应付中心 apfinanceorgs VID-》结算利润中心
	 * vbatchcode 批次号 需求部门pk_reqdept_v -》 pk_reqdept
	 * 
	 * @param vos
	 * @throws BusinessException
	 *
	 */
	private void fillBodyVo(OrderVO[] vos) throws BusinessException {
		Set<String> materials = new HashSet<String>();
		Set<String> casscustvids = new HashSet<String>();
		Set<String> arrvstoorgs = new HashSet<String>();
		Set<String> apfinanceorgs = new HashSet<String>();
		Set<String> orgs = new HashSet<String>();
		Set<String> arrliabcenterVids = new HashSet<String>();
		Set<String> vbatchcode = new HashSet<String>();
		Set<String> depts = new HashSet<String>();// NCC-309814 需求部门vid带oid
		// 表头收货客户Oid有值带出表体收货地区地址、地点
		Map<String, String> recvcustomerOids = new HashMap<String, String>();
		for (OrderVO orderVO : vos) {
			arrvstoorgs.add(orderVO.getHVO().getPk_org_v());
			orgs.add(orderVO.getHVO().getPk_org());
			if (orderVO.getHVO().getPk_recvcustomer() != null) {
				recvcustomerOids.put(orderVO.getHVO().getPk_recvcustomer(), orderVO.getHVO().getPk_org());
			}
			for (OrderItemVO orderItemVO : orderVO.getBVO()) {
				materials.add(orderItemVO.getPk_material());
				casscustvids.add(orderItemVO.getCasscustvid());
				arrvstoorgs.add(orderItemVO.getPk_arrvstoorg_v());
				arrvstoorgs.add(orderItemVO.getPk_flowstockorg_v());
				arrvstoorgs.add(orderItemVO.getPk_arrliabcenter_v());
				arrliabcenterVids.add(orderItemVO.getPk_arrliabcenter_v());
				arrvstoorgs.add(orderItemVO.getPk_reqstoorg_v());
				arrvstoorgs.add(orderItemVO.getPk_psfinanceorg_v());
				arrvstoorgs.add(orderItemVO.getPk_apfinanceorg_v());
				if (orderItemVO.getPk_apfinanceorg_v() != null) {
					apfinanceorgs.add(orderItemVO.getPk_apfinanceorg_v());
				}
				if (orderItemVO.getPk_apliabcenter_v() != null) {
					apfinanceorgs.add(orderItemVO.getPk_apliabcenter_v());
				}
				vbatchcode.add(orderItemVO.getVbatchcode());
				depts.add(orderItemVO.getPk_reqdept_v());// NCC-309814 需求部门vid带oid
			}
		}
		// NCC-309814 采购部门Vid查Oid的值
		HashMap<String, String> oidsByDeptVIDS = NCLocator.getInstance().lookup(IDeptPubService.class)
				.getOIDSByDeptVIDS(depts.toArray(new String[depts.size()]));
		// 根据批次号查询主键
		Map<String, String> vbatchIds = this.getVBatchIdByCode(vbatchcode);
//    Map<String, String> mapvid = new HashMap<String, String>();
//    // 收货利润中心根据vid查询oid
//    ProfitCenterVO[] profits =
//        NCLocator.getInstance().lookup(IProfitCenterPubService.class)
//            .queryProfitCenterVOByIDS(arrliabcenterVids.toArray(new String[0]));
//    Stream.of(profits).forEach(profit -> {mapvid.put(profit.getPk_profitcenter(), profit.getPk_vid());});

		// 查询利润中心oid
		Map<String, String> profitmap = ProfitCenterPubService
				.queryProfitCenterVidByOid(apfinanceorgs.toArray(new String[0]));

		// 根据组织Vid查询Oid的值
		Map<String, String> orgOidsByVrgIDS = OrgUnitPubService
				.getOrgIDSByVIDS(arrvstoorgs.toArray(new String[arrvstoorgs.size()]));
		// 根据物料，查找物料的基本信息
		MaterialVO[] materialsByMec = MaterialPubService.queryMaterialBaseInfoByPks(
				materials.toArray(new String[materials.size()]), new String[] { MaterialVO.PK_MATERIAL,
						MaterialVO.PK_ORG, MaterialVO.PK_GROUP, MaterialVO.PK_MEASDOC, MaterialVO.PK_SOURCE });
		// 物料信息集合
		Map<String, MaterialVO> invBasVOs = getMapMaterialToVo(materialsByMec);
		// 查询物料对应的所有辅单位
		Map<String, List<String>> measdocByVIDMap = this.getCastunitidMapByTempTable(materials);
		// 获取物料下单位得所有换算率
		Map<String, MaterialConvertVO> convertByMaterialAndMeasdocMap = NCLocator.getInstance()
				.lookup(IMaterialPubService.class)
				.queryMaterialConvertByMaterialAndMeasdoc(materials.toArray(new String[materials.size()]),
						this.getpkDepts(measdocByVIDMap), new String[] { MaterialConvertVO.PK_MATERIAL,
								MaterialConvertVO.MEASRATE, MaterialConvertVO.PK_MEASDOC });

		// 根据物料VID数组查询默认采购计量单位
		Map<String, String> measdocIDByPks = MaterialPubService
				.queryPuMeasdocIDByPks(materials.toArray(new String[materials.size()]));
		// 获得物料的基本信息
//    InvInfoQuery invInfoQuery = new InvInfoQuery();
		// InvBasVO 中 pk_measdoc为主单位值，pk_source为版本信息值
//    Map<String, InvBasVO> invBasVOs = invInfoQuery.getInvBasVOs(materials.toArray(new String[materials.size()]));
		// 若输入客户Vid，查找客户的Oid字段
		Map<String, String> customerOidsByVids = CustomerPubService
				.queryCustomerOidsByVids(casscustvids.toArray(new String[casscustvids.size()]));
		// 根据组织获取组织对应的利润中心
		Collection<String> orgOids = orgOidsByVrgIDS.values();
		ProfitCenterVO[] profitCenterVOSByRelateOrgs = NCLocator.getInstance().lookup(IProfitCenterPubService.class)
				.queryProfitCenterVOSByRelateOrgs(orgOids.toArray(new String[orgOids.size()]));
		Map<String, ProfitCenterVO> apliabcentersMapByApfinanceorg = this.getMapBySet(profitCenterVOSByRelateOrgs);

		// 获取结算组织对应的本位币，给表体币种赋值
		Map<String, String> ccurrencyids = OrgUnitPubService
				.queryOrgCurrByPk(orgOids.toArray(new String[orgOids.size()]));

		// 获取组织对应的仓库
//    Map<String, String> directStoreByOrg = StordocPubService.getDirectstore(orgOids.toArray(new String[orgOids.size()]));

		// 存储物料库存组织信息-》仓库
//    Map<String, MaterialStockVO> materialStockInfoByArrOrg = new HashMap<String, MaterialStockVO>();
		// 存储组织所属于组织类型
		Map<String, UFBoolean> typeByOrg = new HashMap<String, UFBoolean>();
		// 存储收货利润中心的值
		Map<String, String> storedocsByOrg = new HashMap<String, String>();

		// 汇率类型编辑的询汇率接口不支持批量查询，在这里定义一个map做缓存数据使用
		Map<String, RateReturnObject> rateCacheMap = new HashMap<String, RateReturnObject>();
		// 根据表头收货客户Oid，查找收货客户得收货地址地区、地点
		Map<String, String> cdevAreaIdByReceOIds = this.getCdevareaId(recvcustomerOids);
		for (OrderVO orderVO : vos) {
			BillHelper<OrderVO> voHelper = new BillHelper<OrderVO>(orderVO);
			int[] rows = new int[voHelper.getItemCount()];
			OrderHeaderVO headerVO = orderVO.getHVO();
			UFBoolean breturn = headerVO.getBreturn();
			// 收货客户
			String pk_recvcustomer = headerVO.getPk_recvcustomer();
			String pk_org = headerVO.getPk_org();
			for (int i = 0; i < orderVO.getBVO().length; i++) {
				rows[i] = i;
				OrderItemVO orderItemVO = orderVO.getBVO()[i];
				if (orderItemVO.getStatus() == 0 || orderItemVO.getStatus() == 2) {
					orderItemVO.setStatus(VOStatus.NEW);
				}
				orderItemVO.setPk_group(headerVO.getPk_group());
				orderItemVO.setPk_org(headerVO.getPk_org());
				orderItemVO.setPk_org_v(headerVO.getPk_org_v());
				// 校验若退货，若数量、价税合计大于0报错
				if (breturn != null && breturn.booleanValue()) {
					// 退货
					UFDouble nastnum = orderItemVO.getNastnum();
					UFDouble norigtaxmny = orderItemVO.getNorigtaxmny();
					if (nastnum.compareTo(UFDouble.ZERO_DBL) > 0
							|| (norigtaxmny != null && norigtaxmny.compareTo(UFDouble.ZERO_DBL) > 0)) {
						ExceptionUtils.wrappBusinessException(nc.vo.ml.NCLangRes4VoTransl.getNCLangRes()
								.getStrByID("4004030_0", "04004030-0428")/*
																			 * @res "订单退货时，表体的数量或价税合计不能为正数，请检查！"
																			 */);
					}
				}
				// 操作员
				orderItemVO.setChandler(AppContext.getInstance().getPkUser());
				// 主单位，不导入，获取默认值
				orderItemVO.setCunitid(invBasVOs.get(orderItemVO.getPk_material()).getPk_measdoc());
				// 扣税类别
				if (orderItemVO.getFtaxtypeflag() == null) {
					orderItemVO.setFtaxtypeflag(headerVO.getFhtaxtypeflag());
				}
				// 税率
				if (orderItemVO.getNtaxrate() == null) {
					orderItemVO.setNtaxrate(headerVO.getNhtaxrate());
				}
				// 折扣
				if (orderItemVO.getNitemdiscountrate() == null) {
					orderItemVO.setNitemdiscountrate(new UFDouble(100));
				}
				// 物料版本
				if (orderItemVO.getPk_srcmaterial() == null) {
					orderItemVO.setPk_srcmaterial(invBasVOs.get(orderItemVO.getPk_material()).getPk_source());
				}
				// 客户
				if (orderItemVO.getCasscustid() == null && orderItemVO.getCasscustvid() != null) {
					orderItemVO.setCasscustid(customerOidsByVids.get(orderItemVO.getCasscustvid()));
				}
				// 增加校验，若收货库存组织与需求库存组织为空，清空表体收货仓库与需求仓库得值
				if (orderItemVO.getPk_arrvstoorg_v() == null) {
					orderItemVO.setPk_recvstordoc(null);
				}
				if (orderItemVO.getPk_reqstoorg_v() == null) {
					orderItemVO.setPk_reqstordoc(null);
				}

				// 收货库存组织 版本
				if (orderItemVO.getPk_arrvstoorg() == null && orderItemVO.getPk_arrvstoorg_v() != null) {
					orderItemVO.setPk_arrvstoorg(orgOidsByVrgIDS.get(orderItemVO.getPk_arrvstoorg_v()));
					if (!this.getOrgType(orderItemVO.getPk_arrvstoorg(), nc.itf.org.IOrgConst.STOCKORGTYPE,
							typeByOrg)) {
						// 若无库存职能直接报错
						ExceptionUtils.wrappBusinessException(nc.vo.ml.NCLangRes4VoTransl.getNCLangRes()
								.getStrByID("4004030_0", "04004030-0417")/*
																			 * @res "该库存组织无库存职能，不能导入，请检查!"
																			 */);
					}
				}
				// 物流组织版本
				if (orderItemVO.getPk_flowstockorg() == null && orderItemVO.getPk_flowstockorg_v() != null) {
					orderItemVO.setPk_flowstockorg(orgOidsByVrgIDS.get(orderItemVO.getPk_flowstockorg_v()));
				} else {
					orderItemVO.setPk_flowstockorg(orderItemVO.getPk_org());
				}
				// 物流组织 未导入时默认取采购组织；导入时取导入值
				if (orderItemVO.getPk_flowstockorg_v() == null) {
					orderItemVO.setPk_flowstockorg_v(orderItemVO.getPk_org_v());
				}
				// 需求库存组织版本
				if (orderItemVO.getPk_reqstoorg() == null && orderItemVO.getPk_reqstoorg_v() != null) {
					orderItemVO.setPk_reqstoorg(orgOidsByVrgIDS.get(orderItemVO.getPk_reqstoorg_v()));
					if (!this.getOrgType(orderItemVO.getPk_reqstoorg(), nc.itf.org.IOrgConst.STOCKORGTYPE, typeByOrg)) {
						// 若无库存职能直接报错
						ExceptionUtils.wrappBusinessException(nc.vo.ml.NCLangRes4VoTransl.getNCLangRes()
								.getStrByID("4004030_0", "04004030-0417")/*
																			 * @res "该库存组织无库存职能，不能导入，请检查!"
																			 */);
					}
				}
				// 结算财务组织版本
				if (orderItemVO.getPk_psfinanceorg() == null && orderItemVO.getPk_psfinanceorg_v() != null) {
					orderItemVO.setPk_psfinanceorg(orgOidsByVrgIDS.get(orderItemVO.getPk_psfinanceorg_v()));
				} else {
					// 判断组织是否属于财务组织
					if (this.getOrgType(orderItemVO.getPk_org(), nc.itf.org.IOrgConst.FINANCEORGTYPE, typeByOrg)) {
						orderItemVO.setPk_psfinanceorg(orderItemVO.getPk_org());
					}
				}
				// 结算财务组织 未导入时默认取采购组织；导入时取导入值
				if (orderItemVO.getPk_psfinanceorg_v() == null) {
					// 判断组织是否属于财务组织
					if (this.getOrgType(orderItemVO.getPk_org(), nc.itf.org.IOrgConst.FINANCEORGTYPE, typeByOrg)) {
						orderItemVO.setPk_psfinanceorg_v(orderItemVO.getPk_org_v());
					}
				}
				// 币种 根据结算财务组织获值
				if (orderItemVO.getCcurrencyid() == null) {
					orderItemVO.setCcurrencyid(ccurrencyids.get(orderItemVO.getPk_psfinanceorg()));
				}
				// 应付组织 版本
				if (orderItemVO.getPk_apfinanceorg() == null && orderItemVO.getPk_apfinanceorg_v() != null) {
					orderItemVO.setPk_apfinanceorg(orgOidsByVrgIDS.get(orderItemVO.getPk_apfinanceorg_v()));
				} else {
					orderItemVO.setPk_apfinanceorg(orderItemVO.getPk_psfinanceorg());
				}
				// 应付组织 未导入时取结算采购组织，导入取导入值
				if (orderItemVO.getPk_apfinanceorg_v() == null) {
					orderItemVO.setPk_apfinanceorg_v(orderItemVO.getPk_psfinanceorg_v());
				}
				// 结算利润中心 版本
				if (orderItemVO.getPk_apliabcenter() == null && orderItemVO.getPk_apliabcenter_v() != null) {
					orderItemVO.setPk_apliabcenter(profitmap.get(orderItemVO.getPk_apliabcenter_v()));
				}
				// 结算利润中心 未导入时取应付组织对应的利润中心，导入取导入值
				if (orderItemVO.getPk_apliabcenter_v() == null && !apliabcentersMapByApfinanceorg.isEmpty()
						&& apliabcentersMapByApfinanceorg.get(orderItemVO.getPk_apfinanceorg()) != null) {
					orderItemVO.setPk_apliabcenter_v(
							apliabcentersMapByApfinanceorg.get(orderItemVO.getPk_apfinanceorg()).getPk_vid());
					orderItemVO.setPk_apliabcenter(
							apliabcentersMapByApfinanceorg.get(orderItemVO.getPk_apfinanceorg()).getPk_profitcenter());
				}
				// 收货仓库\需求仓库 导入取导入值；未导入取默认值
//        if (!headerVO.getBdirect().booleanValue()) {
//          // 若直运时走另外逻辑
//          String pk_reqstordoc = null;
//          if (orderItemVO.getPk_recvstordoc() == null || orderItemVO.getPk_reqstordoc() == null) {
//            // 接口中获取仓库地址
//            if (materialStockInfoByArrOrg == null || materialStockInfoByArrOrg.get(orderItemVO.getPk_material()) == null) {
//              materialStockInfoByArrOrg = MaterialPubService.queryMaterialStockInfo(new String [] {orderItemVO.getPk_material()}, orderItemVO.getPk_arrvstoorg(), new String[] {MaterialStockVO.PK_STORDOC});
//            }
//            if (!materialStockInfoByArrOrg.isEmpty() && materialStockInfoByArrOrg.get(orderItemVO.getPk_material()) != null) {
//              pk_reqstordoc = materialStockInfoByArrOrg.get(orderItemVO.getPk_material()).getPk_stordoc();
//            }
//          }
//          if (orderItemVO.getPk_recvstordoc() == null && pk_reqstordoc != null) {
//            orderItemVO.setPk_recvstordoc(pk_reqstordoc);
//          }
//          if (orderItemVO.getPk_reqstordoc() == null && pk_reqstordoc != null) {
//            orderItemVO.setPk_reqstordoc(pk_reqstordoc);
//          }
//        } else {
//          // 若订单类型为直运设置直运仓
//          if (orderItemVO.getPk_recvstordoc() == null) {
//            orderItemVO.setPk_recvstordoc(directStoreByOrg.get(orderItemVO.getPk_arrvstoorg()));
//          }
//          if (orderItemVO.getPk_reqstordoc() == null) {
//            orderItemVO.setPk_reqstordoc(directStoreByOrg.get(orderItemVO.getPk_arrvstoorg()));
//          }
//        }
				// 收货利润中心版本
				if (orderItemVO.getPk_arrliabcenter() == null && orderItemVO.getPk_arrliabcenter_v() != null) {
					// 根据vid查找oid
					String oid = "";
					if (storedocsByOrg.isEmpty() || storedocsByOrg.get(orderItemVO.getPk_arrliabcenter_v()) == null) {
						ProfitCenterVO profits = NCLocator.getInstance().lookup(IProfitCenterPubService.class)
								.queryProfitCenterByVID(orderItemVO.getPk_arrliabcenter_v());
						storedocsByOrg.put(orderItemVO.getPk_arrliabcenter_v(), profits.getPk_profitcenter());
						oid = profits.getPk_profitcenter();
					} else {
						oid = storedocsByOrg.get(orderItemVO.getPk_arrliabcenter_v());
					}
					orderItemVO.setPk_arrliabcenter(oid);
				}
				// 批次号，若导入之后未查出批次号，则清空表体批次号
				if (orderItemVO.getVbatchcode() != null && vbatchIds.isEmpty()
						&& vbatchIds.get(orderItemVO.getVbatchcode()) == null) {
					orderItemVO.setVbatchcode(null);
				}
				// 批次号主键
				if (orderItemVO.getVbatchcode() != null && !vbatchIds.isEmpty()
						&& vbatchIds.get(orderItemVO.getVbatchcode()) != null) {
					orderItemVO.setPk_batchcode(vbatchIds.get(orderItemVO.getVbatchcode()));
				}
				// NCC-309814 补充需求部门Pk_reqdept
				if (orderItemVO.getPk_reqdept() == null && orderItemVO.getPk_reqdept_v() != null) {
					orderItemVO.setPk_reqdept(oidsByDeptVIDS.get(orderItemVO.getPk_reqdept_v()));
				}

				// 设置表体组织汇率类型等的值
				this.setBodyRateVal(headerVO, orderItemVO, rateCacheMap);
				// 校验单位与报价单位的值
				this.checkoutCasuitAndCquit(orderItemVO, measdocIDByPks, measdocByVIDMap, invBasVOs);
				// 更新表体收货地区收货地点收货地址得值
				if (orderItemVO.getPk_receiveaddress() == null) {
					String pk_receiveaddress = cdevAreaIdByReceOIds
							.get(pk_recvcustomer + pk_org + OrderItemVO.PK_RECEIVEADDRESS);
					orderItemVO.setPk_receiveaddress(pk_receiveaddress);
				}
				if (orderItemVO.getCdevareaid() == null) {
					String cdevareaid = cdevAreaIdByReceOIds.get(pk_recvcustomer + pk_org + OrderItemVO.CDEVAREAID);
					orderItemVO.setCdevareaid(cdevareaid);
				}
				if (orderItemVO.getCdevaddrid() == null) {
					String cdevaddrid = cdevAreaIdByReceOIds.get(pk_recvcustomer + pk_org + OrderItemVO.CDEVADDRID);
					orderItemVO.setCdevaddrid(cdevaddrid);
				}
				// 若只导入税码
				this.calNRate(orderVO, rows, orderItemVO);
			}
			// 设置本位币、汇率相关信息
			this.setCurrencyAndRate(voHelper, rows);
			// 设置需求库存组织与收货库存组织未导入时默认值
			this.defaultOrganization(voHelper, rows);
			// 设置需求公司
			new ReqCorpDefaultValue(voHelper).setDefaultValue(rows);
			// 设置表体利润中心字段
//      this.setArrLiabVals(orderVO,storedocsByOrg,apliabcentersMapByApfinanceorg);
			// 设置发货国，收获国，报税国
			this.registerCountryRemoteCall(voHelper, rows);
			// 计算数量
			this.calculate(orderVO, rows, OrderItemVO.NQTORIGTAXPRICE, convertByMaterialAndMeasdocMap, invBasVOs);
			// 设置计划到货日期
			this.setPlanArriDate(voHelper, rows);

		}
	}

	private void calNRate(OrderVO vo, int[] rows, OrderItemVO orderVO) {
		// 税码
		String ctaxcodeid = orderVO.getCtaxcodeid();
		// 税率
		UFDouble ntaxrate = orderVO.getNtaxrate();
		if (ctaxcodeid != null && ntaxrate == null) {
			// 若导入税码，根据税码询税率
			TaxCode taxCode = new TaxCode();
			taxCode.setImport(UFBoolean.TRUE);// 导入标识，不进行计算逻辑
			taxCode.afterEdit(vo, rows);
		}
	}

	/**
	 *
	 * 根据表头收货客户与组织查询表体地区地址地点
	 * 
	 * @param recvcustomerOids
	 * @return
	 *
	 */
	private Map<String, String> getCdevareaId(Map<String, String> recvcustomerOids) {
		HashMap<String, String> hashMap = new HashMap<String, String>();
		Set<String> defaultReceiveAddress = new HashSet<String>();
		for (Entry<String, String> recvcustomerOid : recvcustomerOids.entrySet()) {
			// 收货客户Oid
			String receiveCustomerid = recvcustomerOid.getKey();
			// 采购组织
			String pk_org = recvcustomerOid.getValue();
			String receiveaddresskey = receiveCustomerid + pk_org + OrderItemVO.PK_RECEIVEADDRESS;
			String defaultReceiveAddres = null;
			if (!hashMap.containsKey(receiveaddresskey)) {
				// 取默认收货地址
				defaultReceiveAddres = CustomerPubService.getDefaultAddress(receiveCustomerid, pk_org);
				hashMap.put(receiveCustomerid + pk_org + OrderItemVO.PK_RECEIVEADDRESS, defaultReceiveAddres);
				defaultReceiveAddress.add(defaultReceiveAddres);

				if (!PubAppTool.isNull(defaultReceiveAddres)) {
					// 取默认收货地区
					String[] defaultReceiveAreas = CustomerPubService
							.getAreaPksByConsignAddress(new String[] { defaultReceiveAddres });
					if (!ArrayUtils.isEmpty(defaultReceiveAreas)) {
						String defaultReceiveArea = defaultReceiveAreas[0];
						hashMap.put(receiveCustomerid + pk_org + OrderItemVO.CDEVAREAID, defaultReceiveArea);
					}
					// 取默认收货地点
					Map<String, String> defaultAddressDoc = AddrdocPubService
							.getAddressDocPksByConsignAddress(new String[] { defaultReceiveAddres });
					String defaultCdevaddrid = defaultAddressDoc.get(defaultReceiveAddres);
					hashMap.put(receiveCustomerid + pk_org + OrderItemVO.CDEVADDRID, defaultCdevaddrid);
				}
			}
		}
		return hashMap;
	}

	/**
	 *
	 * 根据业务委托关系寻值
	 * 
	 * @param card
	 * @param row
	 *
	 */
	private void defaultOrganization(IKeyValue card, int[] rows) {
		// 组织业务委托关系找组织
		OrganizationDefaultValue util = new OrganizationDefaultValue(card, UFBoolean.TRUE);
		util.setClear(false);
		util.setDefaultOrganizationValue(rows);// 需求库存组织修改时根据业务委托关系询收货库存组织
		util.setDefaultStordoc(rows);// 需求库存组织和收货库存组织询值后，询对应的需求仓库收货仓库
//    util.setDefaultOrganizationValueByArrOrg(rows);
		new FlowStockOrgValue(card).setFlowStockOrg(rows);
	}

	/**
	 *
	 * 根据批次号查询主键
	 * 
	 * @param vbatchcode
	 * @return
	 *
	 */
	private Map<String, String> getVBatchIdByCode(Set<String> vbatchcode) {
		Map<String, String> btachIds = new HashMap<String, String>();
		String[] vbatchcodes = vbatchcode.toArray(new String[0]);
		if (nc.vo.scmpub.util.CollectionUtils.isNullForAllTElements(vbatchcodes)) {
			return null;
		}
		SqlBuilder sql = new SqlBuilder();
		sql.append("SELECT DISTINCT PK_BATCHCODE,VBATCHCODE from scm_batchcode where ");
		sql.append(OrderItemVO.VBATCHCODE, vbatchcodes);
		DataAccessUtils util = new DataAccessUtils();
		IRowSet rowset = util.query(sql.toString());
		while (rowset.next()) {
			String vcodeId = rowset.getString(0);// 批次号主键
			String vcode = rowset.getString(1);// 批次号
			btachIds.put(vcode, vcodeId);
		}
		return btachIds;
	}

	/**
	 * 数组转为map，key为pk_material，value为MaterialVO类
	 *
	 * @param materials 物料的详细信息集合
	 * @return
	 *
	 */
	private Map<String, MaterialVO> getMapMaterialToVo(MaterialVO[] materials) {
		Map<String, MaterialVO> materialVOMap = new HashMap<>();
		for (MaterialVO materialVO : materials) {
			materialVOMap.put(materialVO.getPk_material(), materialVO);
		}
		return materialVOMap;
	}

	/**
	 *
	 * 计算数量与价格
	 * 
	 * @param orderVO
	 * @param rows
	 * @param itemKey   根据itemKey计算金额与单价
	 * @param invBasVOs 物料本身的单位
	 * @param rates     换算率集合
	 */
	private void calculate(OrderVO orderVO, int[] rows, String itemKey, Map<String, MaterialConvertVO> changerates,
			Map<String, MaterialVO> invBasVOs) {
		IRelationForItems item = new RelationItemForCal();
		BillHelper<OrderVO> billHelper = new BillHelper<OrderVO>(orderVO);
		WeightVolumePieceCalc volumePieceCalc = new WeightVolumePieceCalc(billHelper, UFBoolean.TRUE);

		String pkOrg = orderVO.getHVO().getPk_org();
		boolean isChangePrice = this.isChangePrice(pkOrg);
		boolean isTaxPricePriorToPrice = this.isTaxPricePriorToPrice(pkOrg);
		String pk_group = orderVO.getHVO().getPk_group();
		boolean groupLobalMnyCal = this.groupLobalMnyCal(pk_group);
		boolean publicLocalMnyCal = this.publicLocalMnyCal();

		boolean isOrigCurToGroupMoney = this.isOrigCurToGroupMoney(pk_group);
		boolean isOrigCurToGlobalMoney = this.isOrigCurToGlobalMoney();

		Map<String, UFBoolean> fixUnitRateAst = this.isFixUnitRate(orderVO, rows, true);
		Map<String, UFBoolean> fixUnitRateQt = this.isFixUnitRate(orderVO, rows, false);
		OrderItemVO[] itemVOs = orderVO.getBVO();
		List<OrderItemVO> orderItemList = Arrays.asList(itemVOs);
		// 是否计算报价换算率
		UFBoolean flagnnum = UFBoolean.FALSE;
		for (OrderItemVO itemVO : orderItemList) {
			String material = itemVO.getPk_material();
			String cunitid = itemVO.getCunitid();
			String castunitid = itemVO.getCastunitid();
			String cqtunitid = itemVO.getCqtunitid();
			String keyAst = material + cunitid + castunitid;
			String keyQt = material + cunitid + cqtunitid;
			String vchangeRate = null;
			if (itemVO.getNnum() != null) {
				// 主数量不为空时才计算报价换算率
				flagnnum = UFBoolean.TRUE;
			}
			if (changerates == null || changerates.get(material + "-" + castunitid) == null) {
				// 物料主单位，若主辅一致，换算率为1
				String pk_measdoc = invBasVOs.get(material).getPk_measdoc();
				if (castunitid.equals(pk_measdoc)) {
					vchangeRate = VCHANGERATE;
				}
			} else {
				vchangeRate = changerates.get(material + "-" + castunitid).getMeasrate();
			}

			// 固定换算率：不取导入值，直接询物料档案默认换算率
			// 浮动换算率：导入时，取导入值；不导入时，询物料档案相应换算率
			if (!fixUnitRateAst.get(keyAst).booleanValue()) {
				// 浮动，换算率值为空且主数量或数量为空，根据物料档案取换算率值，重新寻值
				if (itemVO.getVchangerate() == null && (itemVO.getNnum() == null || itemVO.getNastnum() == null)) {
					if (cunitid.equals(castunitid)) {
						vchangeRate = VCHANGERATE;
					}
					itemVO.setVchangerate(this.scaleUtils.adjustHslScale(vchangeRate));
				}
				// 浮动 为空 计算主数量值
				if (itemVO.getNnum() == null) {
					UFDouble nnum = HslParseUtil.hslMultiplyUFDouble(itemVO.getVchangerate(), itemVO.getNastnum());
					itemVO.setNnum(this.scaleUtils.adjustNumScale(nnum, itemVO.getCunitid()));
				} else {
					// 浮动 不为空 计算换算率
					String vhangerate = HslParseUtil.buildHslString(itemVO.getNnum(), itemVO.getNastnum());
					itemVO.setVchangerate(this.scaleUtils.adjustHslScale(vhangerate));// 处理换算率精度
				}
			} else {
				// 固定 浮动值空
				if (cunitid.equals(castunitid)) {
					vchangeRate = VCHANGERATE;
				}
				itemVO.setVchangerate(this.scaleUtils.adjustHslScale(vchangeRate));
				// 主数量为空 计算值
//        if (itemVO.getNnum() == null) {
				UFDouble nnum = HslParseUtil.hslMultiplyUFDouble(itemVO.getVchangerate(), itemVO.getNastnum());
				itemVO.setNnum(this.scaleUtils.adjustNumScale(nnum, itemVO.getCunitid()));
//        }
			}

			// 报价换算率 固定 为空 ，寻值 计算报价数量得值
			// 报价换算率不导，若报价数量为空，则根据换算率与主数量计算报价数量得值，若报价数量导入则根据主数量与报价数量计算报价换算率得值
			String vchangerate = "";
			if (itemVO.getNqtunitnum() == null || fixUnitRateQt.get(keyQt).booleanValue()) {
				if (cunitid.equals(cqtunitid)) {
					vchangerate = VCHANGERATE;
					itemVO.setNqtunitnum(itemVO.getNnum());
				} else if (castunitid.equals(cqtunitid)) {
					vchangerate = changerates.get(material + "-" + castunitid).getMeasrate();
					itemVO.setNqtunitnum(itemVO.getNastnum());
				} else {
					vchangerate = changerates.get(material + "-" + cqtunitid).getMeasrate();
					UFDouble nastnum = CalculatorUtil.div(itemVO.getNnum(), HslParseUtil.getUFDoubleHsl(vchangerate));
					itemVO.setNqtunitnum(this.scaleUtils.adjustNumScale(nastnum, itemVO.getCqtunitid()));
				}
				if (fixUnitRateQt.get(keyQt).booleanValue()) {
					// 固定
					itemVO.setVqtunitrate(this.scaleUtils.adjustHslScale(vchangerate));
				} else {
					if (flagnnum.booleanValue()) {
						// 浮动，根据报价数量与主数量计算
						String vhangerate = HslParseUtil.buildHslString(itemVO.getNnum(), itemVO.getNqtunitnum());
						// 若为浮动换算率，且报价数量不为空，则根据报价数量与主数量计算报价换算率得值
						itemVO.setVqtunitrate(this.scaleUtils.adjustHslScale(vhangerate));
					} else {
						if (cunitid.equals(cqtunitid)) {
							vchangerate = VCHANGERATE;
						} else if (castunitid.equals(cqtunitid)) {
							vchangerate = changerates.get(material + "-" + castunitid).getMeasrate();
						} else {
							vchangerate = changerates.get(material + "-" + cqtunitid).getMeasrate();
						}
						itemVO.setVqtunitrate(this.scaleUtils.adjustHslScale(vchangerate));
					}
				}
			} else {
				// 浮动 不为空 计算换算率
				if (flagnnum.booleanValue()) {
					// 浮动，根据报价数量与主数量计算
					String vhangerate = HslParseUtil.buildHslString(itemVO.getNnum(), itemVO.getNqtunitnum());
					// 若为浮动换算率，且报价数量不为空，则根据报价数量与主数量计算报价换算率得值
					itemVO.setVqtunitrate(this.scaleUtils.adjustHslScale(vhangerate));
				} else {
					// 固定
					itemVO.setVqtunitrate(this.scaleUtils.adjustHslScale(vchangerate));
				}
//        else {
//          ExceptionUtils.wrappBusinessException(nc.vo.ml.NCLangRes4VoTransl
//              .getNCLangRes().getStrByID("4004030_2",
//                  "2400403002-0259")/*
//                   * @res "该报价单位换算率为浮动换算率，报价数量必输，请重新导入"
//                   */);
//        }
			}

			// 创建数据集实例 初始化数据关系计算用的数据集
			IDataSetForCal data = new OrderDataSetForCal(itemVO, item, orderVO);
			Calculator tool = new Calculator(data, this.scaleUtils);
			// 创建参数实例，在计算的时候用来获得参数条件：是否含税优先等
			Condition cond = new Condition();// 创建参数实例
			// 设置是否进行本币换算
			cond.setIsCalLocalCurr(true);
			// 设置调单价方式调折扣
			cond.setIsChgPriceOrDiscount(isChangePrice);
			// 全局本位币计算方式
			cond.setGlobalLocalCurrencyEnable(publicLocalMnyCal);
			// 集团本位币计算方式
			cond.setGroupLocalCurrencyEnable(groupLobalMnyCal);
			cond.setOrigCurToGlobalMoney(isOrigCurToGlobalMoney);
			cond.setOrigCurToGroupMoney(isOrigCurToGroupMoney);
			// 设置是否固定单位换算率
			cond.setIsFixNchangerate(
					null == fixUnitRateAst.get(keyAst) ? false : fixUnitRateAst.get(keyAst).booleanValue());
			// 是否固定报价单位换算率
			cond.setIsFixNqtunitrate(
					null == fixUnitRateQt.get(keyQt) ? false : fixUnitRateQt.get(keyQt).booleanValue());

			// 设置含税优先还是无税优先
			cond.setIsTaxOrNet(isTaxPricePriorToPrice);
			Integer fbuysellflag = itemVO.getFbuysellflag();
			// 是否跨国业务（购销类型为出口销售、进口采购时，为跨国业务）
			cond.setInternational(BuySellFlagEnum.IMPORT.value().equals(fbuysellflag)
					|| BuySellFlagEnum.OUTPUT.value().equals(fbuysellflag));
			// 两个参数 cond 为计算时的参数条件
//      if (!isTaxPricePriorToPrice) {
//        // 若参数po28为无税单价优先，按照无税单价计算
//        itemKey = OrderItemVO.NQTORIGPRICE;
//      }
			itemKey = this.chekoutPriceCal(itemVO, isTaxPricePriorToPrice);
			tool.calculate(cond, itemKey);
		}

		// 计算总体积、数量、重量
		if (null != volumePieceCalc) {
			volumePieceCalc.calc(rows);// 总体积、数量、重量计算
		}
	}

	private UFDouble setDefultByNull(UFDouble pricaVal) {
		return pricaVal == null ? UFDouble.ZERO_DBL : pricaVal;
	}

	/**
	 *
	 * 判断根据什么值计算， po28含税优先还是无税优先： 触发单价金额算法的优先顺序是：含税金额、无税金额、含税净价、无税净价、含税单价、无税单价
	 * 若导入值唯一，则按照导入值计算；如导入无税单价，但po28未含税优先，按照无税单价计算
	 * 
	 * @param itemVO
	 * @param isTaxPricePriorToPrice 含税优先
	 * @return
	 *
	 */
	private String chekoutPriceCal(OrderItemVO itemVO, boolean isTaxPricePriorToPrice) {
		// 无税金额
		UFDouble norigmny = this.setDefultByNull(itemVO.getNorigmny());
		// 无税净价
		UFDouble nqtorignetprice = this.setDefultByNull(itemVO.getNqtorignetprice());
		// 无税单价
		UFDouble nqtorigprice = this.setDefultByNull(itemVO.getNqtorigprice());

		// 价税合计
		UFDouble norigtaxmny = this.setDefultByNull(itemVO.getNorigtaxmny());
		// 含税净价
		UFDouble nqtorigtaxnetprc = this.setDefultByNull(itemVO.getNqtorigtaxnetprc());
		// 含税单价
		UFDouble nqtorigtaxprice = this.setDefultByNull(itemVO.getNqtorigtaxprice());

		// 是否赠品
		UFBoolean blargess = itemVO.getBlargess() == null ? UFBoolean.FALSE : itemVO.getBlargess();

		// 金额判断，若只有一个有值，按照有值得计算，若两者都有值，按照无税优先还是含税优先
		if (norigmny.compareTo(UFDouble.ZERO_DBL) != 0 && norigtaxmny.compareTo(UFDouble.ZERO_DBL) != 0) {
			// 无税有值，含税有值
			if (isTaxPricePriorToPrice) {
				// 含税优先
				return OrderItemVO.NORIGTAXMNY;
			} else {
				return OrderItemVO.NORIGMNY;
			}
		} else if (norigmny.compareTo(UFDouble.ZERO_DBL) != 0) {
			// 无税有值，含税无值,按照无税计算
			return OrderItemVO.NORIGMNY;
		} else if (norigtaxmny.compareTo(UFDouble.ZERO_DBL) != 0) {
			// 含税有值，无税无值，按照含税计算
			return OrderItemVO.NORIGTAXMNY;
		}

		// 净价判断，若只有一个有值，按照有值得计算，若两者都有值，按照无税优先还是含税优先
		if (nqtorignetprice.compareTo(UFDouble.ZERO_DBL) != 0 && nqtorigtaxnetprc.compareTo(UFDouble.ZERO_DBL) != 0) {
			// 无税有值，含税有值
			if (isTaxPricePriorToPrice) {
				return OrderItemVO.NQTORIGTAXNETPRC;
			} else {
				return OrderItemVO.NQTORIGNETPRICE;
			}
		} else if (nqtorignetprice.compareTo(UFDouble.ZERO_DBL) != 0) {
			// 无税有值，含税无值,按照无税计算
			return OrderItemVO.NQTORIGNETPRICE;
		} else if (nqtorigtaxnetprc.compareTo(UFDouble.ZERO_DBL) != 0) {
			// 含税有值，无税无值，按照含税计算
			return OrderItemVO.NQTORIGTAXNETPRC;
		}

		// 单价判断，若只有一个有值，按照有值得计算，若两者都有值，按照无税优先还是含税优先
		if (nqtorigprice.compareTo(UFDouble.ZERO_DBL) != 0 && nqtorigtaxprice.compareTo(UFDouble.ZERO_DBL) != 0) {
			// 无税有值，含税有值
			if (isTaxPricePriorToPrice) {
				return OrderItemVO.NQTORIGTAXPRICE;
			} else {
				return OrderItemVO.NQTORIGPRICE;
			}
		} else if (nqtorigprice.compareTo(UFDouble.ZERO_DBL) != 0) {
			// 无税有值，含税无值,按照无税计算
			return OrderItemVO.NQTORIGPRICE;
		} else if (nqtorigtaxprice.compareTo(UFDouble.ZERO_DBL) != 0) {
			// 含税有值，无税无值，按照含税计算
			return OrderItemVO.NQTORIGTAXPRICE;
		} else if (UFBoolean.TRUE.equals(blargess) && nqtorigprice.compareTo(UFDouble.ZERO_DBL) == 0
				&& nqtorigtaxprice.compareTo(UFDouble.ZERO_DBL) == 0) {
			// NCC-306842 如果是赠品，并且含税单价、无税单价都是0，则随便返回一个值即可
			return OrderItemVO.NQTORIGTAXPRICE;
		}
		return null;
	}

	/**
	 *
	 * @param panel
	 * @param rows
	 * @param isAst 是辅单位还是报价单位,是否是固定、浮动换算率
	 * @return
	 */
	private Map<String, UFBoolean> isFixUnitRate(OrderVO vo, int[] rows, boolean isAst) {
		Map<String, UFBoolean> map = new HashMap<String, UFBoolean>();
		List<String> pk_materials = new ArrayList<String>();
		List<String> mainunits = new ArrayList<String>();
		List<String> otherunits = new ArrayList<String>();
		for (int row = 0; row < rows.length; row++) {
			String material = vo.getBVO()[rows[row]].getPk_material();
			String cunitid = vo.getBVO()[rows[row]].getCunitid();
			String castunitid = vo.getBVO()[rows[row]].getCastunitid();
			String cqtunitid = vo.getBVO()[rows[row]].getCqtunitid();
			pk_materials.add(material);
			mainunits.add(cunitid);
			if (isAst) {
				otherunits.add(castunitid);
			} else {
				otherunits.add(cqtunitid);
			}
		}
		if (CollectionUtils.isEmpty(pk_materials) || CollectionUtils.isEmpty(otherunits)) {
			return map;
		}
		String[] materialsstr = pk_materials.toArray(new String[0]);
		String[] mainunitsstr = mainunits.toArray(new String[0]);
		String[] otherunitsstr = otherunits.toArray(new String[0]);

		map = MaterialPubService.queryIsFixedRateByMaterialAndMeasdocs(materialsstr, otherunitsstr);
		Map<String, UFBoolean> mapRes = new HashMap<String, UFBoolean>();
		int count = pk_materials.size();
		for (int i = 0; i < count; i++) {
			String keyRes = materialsstr[i] + mainunitsstr[i] + otherunitsstr[i];
			String keyTemp = materialsstr[i] + otherunitsstr[i];
			// 主单位或者要转换的单位为空
			if (StringUtil.isSEmptyOrNull(mainunitsstr[i]) || StringUtil.isSEmptyOrNull(otherunitsstr[i])) {
				mapRes.put(keyRes, UFBoolean.FALSE);
			}
			// 主单位和要转换单位相同
			else if (otherunitsstr[i].equals(mainunitsstr[i])) {
				mapRes.put(keyRes, UFBoolean.TRUE);
			}
			// 主单位和要转换单位不同，查询
			else {
				mapRes.put(keyRes, map.get(keyTemp));
			}
		}
		return mapRes;

	}

	private boolean groupLobalMnyCal(String pk_group) {
		String nc001 = PubSysParamUtil.getNC001(pk_group);
		if (NCPara.NC001_NOUSEGROUPCURRTYPE.getName().equals(nc001)) {
			return false;
		}
		return true;
	}

	private boolean isChangePrice(String pk_org) {
		return PUParaValue.po84.adjust_price == PUSysParamUtil.getPO84(pk_org);
	}

	private boolean isOrigCurToGlobalMoney() {
		String nc002 = PubSysParamUtil.getNC002();
		if (NCPara.NC001_CALCULATEBYORIGCURRTYPE.getName().equals(nc002)) {
			return true;
		}
		return false;
	}

	private boolean isOrigCurToGroupMoney(String pk_group) {
		String nc001 = PubSysParamUtil.getNC001(pk_group);
		if (NCPara.NC001_CALCULATEBYORIGCURRTYPE.getName().equals(nc001)) {
			return true;
		}
		return false;
	}

	private boolean isTaxPricePriorToPrice(String pk_org) {
		boolean flag = true;
		PricePriority pricePriority = PUSysParamUtil.getPO28(pk_org);
		if (!PricePriority.TAXPRICE_PRIOR_TO_PRICE.equals(pricePriority)) {
			flag = false;
		}
		return flag;
	}

	private boolean publicLocalMnyCal() {
		String nc002 = PubSysParamUtil.getNC002();
		if (NCPara.NC002_NOUSEGLOBALCURRTYPE.getName().equals(nc002)) {
			return false;
		}
		return true;
	}

	/**
	 * 报价单位 如果导入，校验报价单位是否属于物料档案中定义的主单位和辅单位，不属于时报错；
	 * 如果未导入，根据业务参数“采购订单默认报价单位”判断取主单位还是辅单位，如果参数为主单位则取主单位，如果参数为辅单位则取采购默认单位。
	 * 校验单位与报价单位的值
	 * 
	 * @param orderItemVO
	 * @param measdocIDByPks
	 * @param measdocByVIDMap
	 * @param invBasVOs
	 *
	 */
	private void checkoutCasuitAndCquit(OrderItemVO orderItemVO, Map<String, String> measdocIDByPks,
			Map<String, List<String>> measdocByVIDMap, Map<String, MaterialVO> invBasVOs) {
		// 单位 若导入 校验单位是否属于物料档案中定义的主单位和辅单位；若未导入，首先取采购默认单位，然后再取主单位。
		if (orderItemVO.getCastunitid() == null) {
			// 若未导入，首先取采购默认单位，然后再取主单位。
			if (measdocIDByPks == null || measdocIDByPks.get(orderItemVO.getPk_material()) == null) {
				orderItemVO.setCastunitid(orderItemVO.getCunitid());
			} else {
				orderItemVO.setCastunitid(measdocIDByPks.get(orderItemVO.getPk_material()));
			}
		} else {
			// 导入 校验单位是否属于物料档案中定义的主单位和辅单位
			if (!invBasVOs.get(orderItemVO.getPk_material()).getPk_measdoc().equals(orderItemVO.getCastunitid())
					&& ((measdocByVIDMap.isEmpty() || measdocByVIDMap.get(orderItemVO.getPk_material()).isEmpty())
							|| !measdocByVIDMap.get(orderItemVO.getPk_material())
									.contains(orderItemVO.getCastunitid()))) {
				ExceptionUtils.wrappBusinessException(nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID("4004020_0",
						"04004020-0126")/*
										 * @res "该单位不属于物料档案中定义的主单位和辅单位，重新导入"
										 */);
			}
		}

		// 报价单位
		// 如果未导入，根据业务参数“采购订单默认报价单位”判断取主单位还是辅单位，如果参数为主单位则取主单位，如果参数为辅单位则取采购默认单位。
		if (orderItemVO.getCqtunitid() == null) {
			// 获得组织级参数po94（报价单位取主单位还是辅单位）
			PUParaValue.po94 po94 = PUSysParamUtil.getPO94(orderItemVO.getPk_org());
			if (po94.equals(PUParaValue.po94.CUNITID)) { // 主单位
				orderItemVO.setCqtunitid(orderItemVO.getCunitid());
			} else {
				orderItemVO.setCqtunitid(orderItemVO.getCastunitid());
			}
		} else {
			// 导入 校验报价单位是否属于物料档案中定义的主单位和辅单位
			if (!invBasVOs.get(orderItemVO.getPk_material()).getPk_measdoc().equals(orderItemVO.getCqtunitid())
					&& ((measdocByVIDMap.isEmpty() || measdocByVIDMap.get(orderItemVO.getPk_material()).isEmpty())
							|| !measdocByVIDMap.get(orderItemVO.getPk_material())
									.contains(orderItemVO.getCqtunitid()))) {
				ExceptionUtils.wrappBusinessException(nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID("4004020_0",
						"04004020-0126")/*
										 * @res "该单位不属于物料档案中定义的主单位和辅单位，重新导入"
										 */);
			}
		}
	}

	/**
	 *
	 * 设置表体组织汇率类型、汇率、日期的值 1.原币币种和本币币种一致时，折本汇率默认1，不取导入值；组织汇率类型、组织汇率来源日期为空。
	 *
	 * @param headerVO
	 * @param orderItemVO
	 * @param bodyRateVals 存储汇率的集合
	 *
	 */
	private void setBodyRateVal(OrderHeaderVO headerVO, OrderItemVO orderItemVO,
			Map<String, RateReturnObject> rateCacheMap) {
		// 组织汇率类型
		String cratetype = orderItemVO.getCratetype();
		// 组织汇率来源日期
		UFLiteralDate dratedate = orderItemVO.getDratedate();
		// 折本汇率
		UFDouble nexchangerate = orderItemVO.getNexchangerate();

		// 币种
		String corigcurrencyid = headerVO.getCorigcurrencyid();
		// 本币
		String ccurrencyid = orderItemVO.getCcurrencyid();
		// 订单日期
		UFDate date = headerVO.getDbilldate();

		if (corigcurrencyid.equals(ccurrencyid)) {
			orderItemVO.setNexchangerate(UFDouble.ONE_DBL);
			orderItemVO.setCratetype(null);
			orderItemVO.setDratedate(null);
			orderItemVO.setFratecategory(null);
		} else {
			if (cratetype != null) {
				UFBoolean flag = UFBoolean.FALSE;
				if (RateTypeConstant.RATE_TYPE_MIDDLE.equals(cratetype)
						|| RateTypeConstant.RATE_TYPE_SELLING.equals(cratetype)
						|| RateTypeConstant.RATE_TYPE_FIX.equals(cratetype)
						|| RateTypeConstant.RATE_TYPE_CUSTOM.equals(cratetype)) {
					flag = UFBoolean.TRUE;
				}
				if (!flag.booleanValue()) {
					ExceptionUtils.wrappBusinessException(nc.vo.ml.NCLangRes4VoTransl.getNCLangRes()
							.getStrByID("4004030_2", "2400403002-0356")/*
																		 * @res
																		 * "只支持组织汇率类型为:基准汇率方案-中间汇率,基准汇率方案-卖出汇率,自定义汇率,固定汇率，当前存在不支持的组织汇率类型，不能导入，请检查"
																		 */);
				}
				// 用汇率类型+原币+本币拼接作为rateCacheMap的key
				String key = orderItemVO.getCratetype() + corigcurrencyid + ccurrencyid;
				if (!rateCacheMap.containsKey(key)) {
					// 录入汇率类型，判断是否是自定义汇率或是固定汇率。
					RateReturnObject ratereturn = CurrencyRatePubService
							.getCurrencyRateByRateType(orderItemVO.getCratetype(), corigcurrencyid, ccurrencyid, date);
					// 折本汇率询不到提示“组织汇率来源类型询不到折本汇率，不能导入，请检查”。
					if (ratereturn == null || (ratereturn != null
							&& (ratereturn.getRate_category() != 7 && ratereturn.getRate_category() != 5)
							&& ratereturn.getRate().compareTo(UFDouble.ZERO_DBL) == 0)) {
						ExceptionUtils.wrappBusinessException(nc.vo.ml.NCLangRes4VoTransl.getNCLangRes()
								.getStrByID("4004030_2", "2400403002-0257")/*
																			 * @res "组织汇率来源类型询不到折本汇率，不能导入，请检查"
																			 */);
					}
					// 增加校验，若为自定义或固定，判断是否导入折本汇率，若未导入则报错
					if ((ratereturn.getRate_category() == 7 || ratereturn.getRate_category() == 5)
							&& nexchangerate == null) {
						ExceptionUtils.wrappBusinessException(nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID(
								"4004030_2", "2400403002-0308")/*
																 * @res "当组织汇率类型为自定义汇率或固定汇率时，折本汇率为空不能导入，请检查！"
																 */);
					}

					rateCacheMap.put(key, ratereturn);
				}
				RateReturnObject ratereturnobject = rateCacheMap.get(key);
				// 若导入三者，不进行后续逻辑,非自定义与固定
				if (ratereturnobject != null
						&& (ratereturnobject.getRate_category() != 5 && ratereturnobject.getRate_category() != 7)) {
					if (cratetype != null && dratedate != null && nexchangerate != null) {
						orderItemVO.setFratecategory(ratereturnobject.getRate_category());
						return;
					}
				}

				if (ratereturnobject != null && (ratereturnobject.getRate_category() == 5
						|| ratereturnobject.getRate_category() == 7 || ratereturnobject.getRate_category() == 0
						|| ratereturnobject.getRate_category() == 2)) {
					// 固定，自定义，取录入的汇率
//          if(ratereturnobject.getRate_category()==5 || ratereturnobject.getRate_category() ==7) {
//            orderItemVO.setCratetype(ratereturnobject.getPk_ratetype());
//            orderItemVO.setFratecategory(ratereturnobject.getRate_category());
//          }else {
//            //重新询汇率
//            orderItemVO.setCratetype(ratereturnobject.getPk_ratetype());
//            orderItemVO.setDratedate(ratereturnobject.getDate());
//            orderItemVO.setFratecategory(ratereturnobject.getRate_category());
//            orderItemVO.setNexchangerate(ratereturnobject.getRate());
//          }
					// 若录入取录入值
					// 若导入汇率类型与折本汇率，日期清空
					if (cratetype != null && nexchangerate != null) {
						orderItemVO.setDratedate(null);
					} else {
						orderItemVO.setDratedate(
								ratereturnobject.getDate() == null ? dratedate : ratereturnobject.getDate());
					}
					orderItemVO.setCratetype(cratetype);
					orderItemVO.setFratecategory(ratereturnobject.getRate_category());
					orderItemVO.setNexchangerate(nexchangerate == null ? ratereturnobject.getRate() : nexchangerate);
				} else {
					orderItemVO.setCratetype(null);
					orderItemVO.setDratedate(null);
					orderItemVO.setFratecategory(null);
				}
			} else {
				// 组织汇率类型为空
				// 2） 只导入折本汇率：折本汇率取导入值，组织汇率类型、组织汇率来源日期为空。
				// 3） 只导入组织汇率来源日期：提示“不允许仅导入组织汇率来源日期，请导入组织汇率来源类型或折本汇率”。
				if (orderItemVO.getNexchangerate() == null && orderItemVO.getDratedate() != null) {
					ExceptionUtils.wrappBusinessException(nc.vo.ml.NCLangRes4VoTransl.getNCLangRes()
							.getStrByID("4004030_2", "2400403002-0258")/*
																		 * @res "不允许仅导入组织汇率来源日期，请导入组织汇率来源类型或折本汇率"
																		 */);
				}
			}
		}
	}

	/**
	 *
	 * 设置发货国、报货国
	 * 
	 * @param rows
	 * @param voHelper2
	 *
	 */
	private void registerCountryRemoteCall(BillHelper<OrderVO> voHelper, int[] rows) {
		List<ICountrySetter> countryList = new ArrayList<ICountrySetter>();
		OrderSendCountrySetter setter = new OrderSendCountrySetter(voHelper, rows);
		setter.setReset(true);
		countryList.add(setter);// 发货国
		countryList.add(new OrderReceiveCountrySetter(voHelper, rows));// 收货国
		countryList.add(new OrderTaxCountrySetter(voHelper, rows));// 报税国
		setter.setCountry();
		OrderVatValueFillRule vatrule = new OrderVatValueFillRule(voHelper, rows, countryList);
		vatrule.prepare();
		vatrule.setExcelImport(true);
		vatrule.process();
		this.remoteCaller.put(OrderVatValueFillRule.class.getName(), vatrule);
	}

	/**
	 *
	 * 计算计划到期日期
	 * 
	 * @param orderVO
	 *
	 */
	private void setPlanArriDate(BillHelper<OrderVO> voHelper, int[] rows) {
		new PlanArriveDate(voHelper).setPlanArriveDate(rows);
	}

	/**
	 *
	 * 设置表体本位币与汇率信息
	 * 
	 * @param orderVO
	 *
	 */
	private void setCurrencyAndRate(BillHelper<OrderVO> voHelper, int[] rows) {
		CurrencyAndExchangerate currency = new CurrencyAndExchangerate(voHelper);
//    currency.setCurrencyAndExchangeRate(rows);
		currency.setCurrencyAndGroupRate(rows);
	}

	/**
	 *
	 * 设置收货利润中心的值： 1.导入取导入值。 2.未导入 ①从收货仓库对应的利润中心带。 ② 仓库未带出，则从收货库存组织带， ③没有则从财务组织带。
	 * ④若没有则从结算利润中心带出 pk_apliabcenter 结算利润中心最新版本 收货仓库 recvstordocs-》
	 * 
	 * @param orderItemVO
	 * @param storedocsByOrg                 缓存集合 key（仓库）value利润中心
	 * @param apliabcentersMapByApfinanceorg 收货库存组织获取的利润中心
	 * @throws BusinessException
	 *
	 */
//  private void setArrLiabVals(OrderVO orderItemVO, Map<String, String> storedocsByOrg, Map<String, ProfitCenterVO> apliabcentersMapByApfinanceorg) throws BusinessException {
//    Set<String> recvstordocs = new HashSet<String>();
//    Map<String,String> vidByOids = new HashMap<String,String>();
//    for (OrderItemVO itemVO : orderItemVO.getBVO()) {
//      if (!StringUtil.isSEmptyOrNull(itemVO.getPk_recvstordoc())) {
//        recvstordocs.add(itemVO.getPk_recvstordoc());
//      }
//    }
//    if (recvstordocs.isEmpty()) {
//      return;
//    }
//    // 仓库获取利润中心
//    StordocVO[] stordocByPks = StordocPubService.queryStordocByPks(recvstordocs.toArray(new String[recvstordocs.size()]), new String[] { StordocVO.PROFITCENTRE  });
//    for (StordocVO stordocVO : stordocByPks) {
//      storedocsByOrg.put(stordocVO.getPk_stordoc(), stordocVO.getProfitcentre());
//    }
//    Collection<String> storedocs = storedocsByOrg.values();
//    ProfitCenterVO[] profits = NCLocator.getInstance().lookup(IProfitCenterPubService.class).queryProfitCenterVOByIDS(storedocs.toArray(new String[storedocs.size()]));
//    for (ProfitCenterVO profit : profits) {
//      vidByOids.put(profit.getPk_profitcenter(), profit.getPk_vid());
//    }
//    // 设置表体的利润中心值
//    for (OrderItemVO itemVO : orderItemVO.getBVO()) {
//      if (itemVO.getPk_arrliabcenter_v() == null) {
//        if (storedocsByOrg.containsKey(itemVO.getPk_recvstordoc()) && storedocsByOrg.get(itemVO.getPk_recvstordoc()) != null) {
//          itemVO.setPk_arrliabcenter(storedocsByOrg.get(itemVO.getPk_recvstordoc()));
//          itemVO.setPk_arrliabcenter_v(vidByOids.get(itemVO.getPk_arrliabcenter_v()));
//        } else if(itemVO.getPk_apliabcenter_v() != null) {
//          itemVO.setPk_arrliabcenter(itemVO.getPk_apliabcenter());
//          itemVO.setPk_arrliabcenter_v(itemVO.getPk_apliabcenter_v());
//        }
//      }
//    }
//
//  }

	/**
	 *
	 * 判断组织是否属于什么类型
	 * 
	 * @param pk_org    组织
	 * @param type      类型
	 * @param typeByOrg 类型分类
	 * @return
	 *
	 */
	private boolean getOrgType(String pk_org, String type, Map<String, UFBoolean> typeByOrg) {
		if (pk_org == null) {
			return false;
		}
		// 将组织和类型联合作为key，组织是否属于类型作为value
		String key = pk_org + type;
		if (typeByOrg.containsKey(key)) {
			return typeByOrg.get(key).booleanValue();
		}

		boolean istype = OrgUnitPubService.isTypeOf(pk_org, type);
		typeByOrg.put(key, UFBoolean.valueOf(istype));
		return istype;
	}

	/**
	 *
	 * 传入的值转Map
	 * 
	 * @param profitCenterVOSByRelateOrgs
	 * @return
	 *
	 */
	private Map<String, ProfitCenterVO> getMapBySet(ProfitCenterVO[] profitCenterVOSByRelateOrgs) {
		Map<String, ProfitCenterVO> pmap = new HashMap<>();
		for (ProfitCenterVO pvo : profitCenterVOSByRelateOrgs) {
			if (pvo.getPforgvos() != null && pvo.getPforgvos().length > 0) {
				pmap.put(pvo.getPforgvos()[0].getPk_businessunit(), pvo);
			}
		}
		return pmap;
	}

	/**
	 *
	 * 根据传入的map获取value值，返回类型为set
	 *
	 * @param planPandocIDs
	 * @return
	 *
	 */
	public String[] getpkDepts(Map<String, List<String>> planPandocIDs) {
		Set<String> pk_deptIds = new HashSet<String>();
		for (List<String> plans : planPandocIDs.values()) {
			for (String deptIds : plans) {
				pk_deptIds.add(deptIds);
			}
		}
		return pk_deptIds.toArray(new String[pk_deptIds.size()]);
	}

	/**
	 *
	 * 查找物料所有得辅单位
	 * 
	 * @param material    物料集合
	 * @param castunitids 单位集合
	 * @return
	 *
	 */
	private Map<String, List<String>> getCastunitidMapByTempTable(Set<String> materials) {
		Map<String, List<String>> map = new HashMap<String, List<String>>();
		SqlBuilder sql = new SqlBuilder();
		sql.append("SELECT DISTINCT pk_material, pk_measdoc, pk_materialconvert , ispumeasdoc ");
		sql.append(" FROM bd_materialconvert WHERE dr=0 and ");
		IDExQueryBuilder builder = new IDExQueryBuilder(PUTempTable.TMP_PO_21_67.name());
		sql.append(builder.buildSQL("pk_material", materials.toArray(new String[materials.size()])));
		IRowSet rowset = new DataAccessUtils().query(sql.toString());
		while (rowset.next()) {
			String pk_material = rowset.getString(0);// 物料
			String pk_measdoc = rowset.getString(1);// 辅单位
			if (map.get(pk_material) == null) {
				List<String> list = new ArrayList<String>();
				list.add(pk_measdoc);
				map.put(pk_material, list);
			} else {
				map.get(pk_material).add(pk_measdoc);
			}
		}
		return map;
	}

	/**
	 * 补充表头VO 对应得集合 需带出得值 采购员 -》 cemployeeids-》采购部门 （Vid、Oid） 收货客户 -》
	 * recvcustomers-》收货地址（收货地点、收货地区） 采购组织 -》 orgs (oid)-》采购组织Vid 供应商 -》 suppliers
	 * (vid)-》供应商Oid 开票供应商 -》 invcsuplliers (vid)-》开票供应商Oid 订单类型 -》 billtypes -》业务流程
	 * 采购部门 -》 depts (vid)-》采购部门Oid 付款协议 payterms -》表体付款协议信息
	 *
	 * @param vos
	 * @throws BusinessException
	 *
	 */
	private void fillHeadVo(OrderVO[] vos) throws BusinessException {
		Set<String> orgs = new HashSet<String>();
		Set<String> depts = new HashSet<String>();
		List<String> billtypes = new ArrayList<String>();
		Set<String> suppliers = new HashSet<String>();
		Set<String> cemployeeids = new HashSet<String>();
		Set<String> recvcustomers = new HashSet<String>();
		Set<String> invcsuplliers = new HashSet<String>();
		Set<String> payterms = new HashSet<String>();
		for (OrderVO orderVO : vos) {
			orgs.add(orderVO.getHVO().getPk_org());
			depts.add(orderVO.getHVO().getPk_dept_v());
			billtypes.add(orderVO.getHVO().getCtrantypeid());
			suppliers.add(orderVO.getHVO().getPk_supplier_v());
			cemployeeids.add(orderVO.getHVO().getCemployeeid());
			recvcustomers.add(orderVO.getHVO().getPk_recvcustomer_v());
			invcsuplliers.add(orderVO.getHVO().getPk_invcsupllier_v());
			if (orderVO.getHVO().getPk_payterm() != null) {
				payterms.add(orderVO.getHVO().getPk_payterm());
			}
		}

		// 采购组织Oid查询Vid的值
		Map<String, String> vidsByOrgIDS = OrgUnitPubService.getNewVIDSByOrgIDS(orgs.toArray(new String[orgs.size()]));
		// 订单类型查询订单类型编码
		Map<String, String> trantypecodeByids = PfServiceScmUtil
				.getTrantypecodeByids(billtypes.toArray(new String[billtypes.size()]));
		// 采购部门Vid查Oid的值
		HashMap<String, String> oidsByDeptVIDS = NCLocator.getInstance().lookup(IDeptPubService.class)
				.getOIDSByDeptVIDS(depts.toArray(new String[depts.size()]));
		// 根据采购组织获得组织本位币
		Map<String, String> currByOrgs = OrgUnitPubService.queryOrgCurrByPk(orgs.toArray(new String[orgs.size()]));
		// 供应商Vid查询供应商Oid的值
		Map<String, String> supplierOidsByVid = SupplierPubService
				.querySupplierOidsByVids(suppliers.toArray(new String[suppliers.size()]));
		// 开票供应商Vid查询供应商Oid的值
		Map<String, String> incvSupplierOidsByVid = SupplierPubService
				.querySupplierOidsByVids(invcsuplliers.toArray(new String[invcsuplliers.size()]));
		// 收货客户Vid查询收货客户Oid得值
		Map<String, String> customerOidsByVid = CustomerPubService
				.queryCustomerOidsByVids(recvcustomers.toArray(new String[recvcustomers.size()]));

		// 存储供应商档案的数据
		Map<String, SupplierInfo> supplierInfosBySuplierAndOrg = new HashMap<String, SupplierInfo>();
		// 存储查询到得采购部门Oid的数据
		Map<String, String> cemployeeidsBycemIdAndOrg = new HashMap<String, String>();
		// 存储查询到得业务流程的数据
		Map<String, String> busiTypesByTypeAndOrg = new HashMap<String, String>();
		// 获取供应商Oid的集合
//    Set<String> supplierSet = new HashSet<String>(supplierOidsByVid.values());
		Collection<String> OidsValues = supplierOidsByVid.values();
		// 获取供应商默认的开户银行
		Map<String, String[]> defaultBankAccbasVOBySupplier = SupplierPubService
				.getDefaultBankAccbasVOBySupplier(OidsValues.toArray(new String[OidsValues.size()]));

		// 获取是否直运
		Collection<String> typeCodevalues = trantypecodeByids.values();
		Map<String, UFBoolean> directPursByTypeCode = TrantypeUtil.getInstance()
				.getDirectPurchaseAttr(typeCodevalues.toArray(new String[typeCodevalues.size()]));
		// 存储查询到得采购部门Vid的数据
		Map<String, String> cemployVidByOid = new HashMap<String, String>();
		// 存储开票供应商Oid查询供应商Vid的值
		Map<String, String> incvSupplierVidsByOid = new HashMap<String, String>();
		// 设置表头的值
		for (OrderVO orderVO : vos) {
			OrderHeaderVO headerVO = orderVO.getHVO();
			SupplierInfo supplierInfo = null;
			if (headerVO.getStatus() == 0 || headerVO.getStatus() == 2) {
				headerVO.setStatus(VOStatus.NEW);
			}
			headerVO.setNversion(UFDouble.ROUND_DOWN);// 版本
			// 单据状态为自由
			headerVO.setForderstatus(POEnumBillStatus.FREE.toIntValue());
			// 制单人
			headerVO.setAttributeValue(OrderHeaderVO.BILLMAKER, AppContext.getInstance().getPkUser());
			// 制单日期
			headerVO.setDmakedate(AppContext.getInstance().getBusiDate());
			// 补货
			headerVO.setBisreplenish(UFBoolean.FALSE);
			// 单据日期
			if (headerVO.getDbilldate() == null) {
				headerVO.setDbilldate(AppContext.getInstance().getBusiDate());
			}

			if (headerVO.getPk_supplier() == null) {
				headerVO.setPk_supplier(supplierOidsByVid.get(headerVO.getPk_supplier_v()));
			}
			if (headerVO.getPk_org_v() == null) {
				headerVO.setPk_org_v(vidsByOrgIDS.get(headerVO.getPk_org()));
			}
			// 订单类型编码
			if (headerVO.getVtrantypecode() == null) {
				headerVO.setVtrantypecode(trantypecodeByids.get(headerVO.getCtrantypeid()));
				headerVO.setBdirect(directPursByTypeCode.get(headerVO.getVtrantypecode()));// 设置是否直运
			}
			// 业务流程
			if (headerVO.getPk_busitype() == null) {
				String busitype = null;
				if (busiTypesByTypeAndOrg == null
						|| busiTypesByTypeAndOrg.get(headerVO.getVtrantypecode() + headerVO.getPk_org()) == null) {
					busitype = NCLocator.getInstance().lookup(IPFConfig.class).retBusitypeCanStart(
							POBillType.Order.getCode(), headerVO.getVtrantypecode(), headerVO.getPk_org(),
							headerVO.getBillmaker());
					busiTypesByTypeAndOrg.put(headerVO.getVtrantypecode() + headerVO.getPk_org(), busitype);
				} else {
					busitype = busiTypesByTypeAndOrg.get(headerVO.getVtrantypecode() + headerVO.getPk_org());
				}
				headerVO.setPk_busitype(busitype);
			}

			// 若供应商档案中设置采购的信息且有值，则获取供应商档案的值
			if (supplierInfosBySuplierAndOrg.get(headerVO.getPk_supplier() + headerVO.getPk_org()) == null) {
				supplierInfo = NCLocator.getInstance().lookup(IOrderSupplierQuery.class)
						.querySupplier(headerVO.getPk_supplier(), headerVO.getPk_org());
				supplierInfosBySuplierAndOrg.put(headerVO.getPk_supplier() + headerVO.getPk_org(), supplierInfo);
			} else {
				supplierInfo = supplierInfosBySuplierAndOrg.get(headerVO.getPk_supplier() + headerVO.getPk_org());
			}

			// 订单日期
			if (headerVO.getDbilldate() == null) {
				headerVO.setDbilldate(AppContext.getInstance().getBusiDate());
			}
			// 整单扣税类别
			if (headerVO.getFhtaxtypeflag() == null) {
				headerVO.setFhtaxtypeflag(EnumDiscounttaxtype.TAXOUT.toIntValue());
			}

			// 采购员 若导入则以导入为主;若未导入且物料档案有值，则取物料档案的值;
			if (headerVO.getCemployeeid() != null) {
				// 若导入，需带出采购部门得值
				String psndocID = null;
				if (cemployeeidsBycemIdAndOrg == null
						|| cemployeeidsBycemIdAndOrg.get(headerVO.getPk_org() + headerVO.getCemployeeid()) == null) {
					psndocID = PsndocPubService.queryDeptIDByPsndocID(headerVO.getPk_org(), headerVO.getCemployeeid());
					cemployeeidsBycemIdAndOrg.put(headerVO.getPk_org() + headerVO.getCemployeeid(), psndocID);
				} else {
					psndocID = cemployeeidsBycemIdAndOrg.get(headerVO.getPk_org() + headerVO.getCemployeeid());
				}
				headerVO.setPk_dept(psndocID);
				String cemployVid = "";
				if (!cemployVidByOid.isEmpty() && cemployVidByOid.get(psndocID) != null) {
					// map中有，从map中获取
					cemployVid = cemployVidByOid.get(psndocID);
				} else {
					IDeptPubService serviceD = NCLocator.getInstance().lookup(IDeptPubService.class);
					Map<String, String> vids = serviceD.getLastVIDSByDeptIDS(new String[] { psndocID });
					cemployVidByOid.putAll(vids);
					cemployVid = cemployVidByOid.get(psndocID);
				}
				// 根据部门Oid获得Vid
				headerVO.setPk_dept_v(cemployVid);
			} else if (headerVO.getCemployeeid() == null && supplierInfo.getRespPerson() != null) {
				headerVO.setCemployeeid(supplierInfo.getRespPerson());
			}
			// 采购部门
			if (headerVO.getPk_dept() == null && headerVO.getPk_dept_v() != null) {
				headerVO.setPk_dept(oidsByDeptVIDS.get(headerVO.getPk_dept_v()));
			}
			// 开票供应商
			if (headerVO.getPk_invcsupllier() == null && headerVO.getPk_invcsupllier_v() != null) {
				// 若导入则以导入为主
				headerVO.setPk_invcsupllier(incvSupplierOidsByVid.get(headerVO.getPk_supplier()));
			} else if (supplierInfo.getBillingSupplier() != null && headerVO.getPk_invcsupllier() == null) {
				// 开票供应商 若未导入且物料档案有值，则取物料档案的值(开票供应商Vid字段未设置);
				headerVO.setPk_invcsupllier(supplierInfo.getBillingSupplier());
				String[] pks = { supplierInfo.getBillingSupplier() };
				if (incvSupplierVidsByOid.isEmpty()
						|| incvSupplierVidsByOid.get(supplierInfo.getBillingSupplier()) == null) {
					// 调用scmpub封装的方法根据供应商oid查询vid
					incvSupplierVidsByOid.putAll(SupplierPubService.querySupplierVidsByOids(pks));
				}
				headerVO.setPk_invcsupllier_v(incvSupplierVidsByOid.get(supplierInfo.getBillingSupplier()));
			} else if (supplierInfo.getBillingSupplier() == null && headerVO.getPk_invcsupllier() == null
					&& headerVO.getPk_invcsupllier_v() == null) {
				// 若供应商档案无值且未导入 取供应商的值
				headerVO.setPk_invcsupllier(headerVO.getPk_supplier());
				headerVO.setPk_invcsupllier_v(headerVO.getPk_supplier_v());
			}
			// 运输方式 若导入以导入为主；若未导入且物料档案有值，获取物料档案值
			if (headerVO.getPk_transporttype() == null && supplierInfo.getTransportType() != null) {
				headerVO.setPk_transporttype(supplierInfo.getTransportType());
			}
			// 付款协议 若导入以导入为主；若未导入且物料档案有值，获取物料档案值
			if (headerVO.getPk_payterm() == null && supplierInfo.getDefaultPaymentTerm() != null) {
				headerVO.setPk_payterm(supplierInfo.getDefaultPaymentTerm());
				payterms.add(headerVO.getPk_payterm());
			}
			// 币种 若导入以导入为主；若未导入且物料档案有值，获取物料档案值;若未导入且供应商档案无值 获取组织本位币
			if (supplierInfo.getDefaultCurrency() != null && headerVO.getCorigcurrencyid() == null) {
				headerVO.setCorigcurrencyid(supplierInfo.getDefaultCurrency());
			} else if (headerVO.getCorigcurrencyid() == null) {
				headerVO.setCorigcurrencyid(currByOrgs.get(headerVO.getPk_org()));
			}
			// 开户银行 若导入以导入为主；若未导入且物料档案有值，获取物料档案值
			if (headerVO.getPk_bankdoc() == null && supplierInfo.getBankAccount() != null) {
				headerVO.setPk_bankdoc(supplierInfo.getBankAccount());
			}
			// 供应商发货地址 若导入以导入为主；若未导入且物料档案有值，获取物料档案值;表体得供应商发货地址获取表头得供应商发货地址得值
			if (headerVO.getPk_deliveradd() == null && supplierInfo.getAddress() != null) {
				headerVO.setPk_deliveradd(supplierInfo.getAddress());
			}
			// 付款协议：若导入以导入为主； 未导入 取供应商档案默认的付款协议
			if (headerVO.getPk_payterm() == null && supplierInfo.getDefaultPaymentTerm() != null) {
				headerVO.setPk_payterm(supplierInfo.getDefaultPaymentTerm());
			}

			// 收货客户
			if (headerVO.getPk_recvcustomer() == null && headerVO.getPk_recvcustomer_v() != null) {
				headerVO.setPk_recvcustomer(customerOidsByVid.get(headerVO.getPk_recvcustomer_v()));
			}

			// 开户银行
			if (headerVO.getPk_bankdoc() == null
					&& defaultBankAccbasVOBySupplier.get(headerVO.getPk_supplier()) != null) {
				String defaultBankAcc = SupplierPubService.getDefaultBankAcc(headerVO.getPk_supplier());
				headerVO.setPk_bankdoc(defaultBankAcc);
				headerVO.setAttributeValue(OrderHeaderVO.VBANKACCOUNT,
						defaultBankAccbasVOBySupplier.get(headerVO.getPk_supplier())[1]);
			}

			// 退货/库基于原订单补货
			if (headerVO.getBrefwhenreturn() == null) {
				headerVO.setBrefwhenreturn(UFBoolean.FALSE);
			}
			// 退货
			if (headerVO.getBreturn() == null) {
				headerVO.setBreturn(UFBoolean.FALSE);
			}
			// 是否直运
			if (headerVO.getBdirect() == null) {
				headerVO.setBdirect(UFBoolean.FALSE);
			}
		}
		// 根据付款协议主键查询付款协议数据，设置表体协议数据
		this.setPayMents(vos, payterms);
	}

	/**
	 *
	 * 设置表体付款协议数据
	 * 
	 * @param vos
	 * @param payterms
	 *
	 */
	private void setPayMents(OrderVO[] vos, Set<String> payterms) {
		// 设置表体获取付款协议的值
		// Map<String, OrderPaymentVO[]> paymentVOs = this.getOrderPaymentVOs(payterms);
		// YBP-SCM-BUG-213 NCC-368292 导入多单且付款协议相同时，只导入成功了第一单，后面几单都没导入成功
		Map<String, PaymentVO> paymentVOs = this.queryPaymentVOs(payterms);
		for (OrderVO orderVO : vos) {
			BillHelper<OrderVO> helper = new BillHelper<OrderVO>(orderVO);
			OrderHeaderVO headerVO = orderVO.getHVO();
			// 设置付款协议
			if (!paymentVOs.isEmpty() && paymentVOs.get(headerVO.getPk_payterm()) != null) {
				// OrderPaymentVO[] orderPaymentVOs = paymentVOs.get(headerVO.getPk_payterm());
				PaymentVO paymentvo = paymentVOs.get(headerVO.getPk_payterm());
				OrderPaymentVO[] newOrderPaymentVOs = this.getOrderPaymentVOs(paymentvo);
				// 如果付款计划相同，这里是一个对象，第一条保存完成之后，会有主键冲突的问题
				// OrderPaymentVO[] newOrderPaymentVOs = (OrderPaymentVO[])new
				// DeepCloneTool().deepClone(orderPaymentVOs);
				helper.setBodyVOs(newOrderPaymentVOs, OrderPaymentVO.class);
			}
		}
	}

	/**
	 * YBP-SCM-BUG-213 NCC-368292 导入多单且付款协议相同时，只导入成功了第一单，后面几单都没导入成功 获取付款协议档案
	 * 
	 * @param pk_payterm
	 * @return
	 */
	private Map<String, PaymentVO> queryPaymentVOs(Set<String> pk_payterm) {
		Map<String, PaymentVO> paymentVOMaps = new HashMap<String, PaymentVO>();
		if (pk_payterm.size() == 0) {
			return paymentVOMaps;
		}
		SuperVO[] vos = PaymentService.queryPaymentByIds(pk_payterm.toArray(new String[pk_payterm.size()]),
				PaymentVO.class);
		if (vos != null && vos.length > 0) {
			for (SuperVO vo : vos) {
				if (vo instanceof PaymentVO) {
					PaymentVO paymentVo = (PaymentVO) vo;
					String hid = paymentVo.getPk_payment();
					paymentVOMaps.put(hid, paymentVo);
				}
			}
		}
		return paymentVOMaps;
	}

	/**
	 * YBP-SCM-BUG-213 NCC-368292 导入多单且付款协议相同时，只导入成功了第一单，后面几单都没导入成功
	 * 根据付款协议档案生成采购订单的付款计划子表数据
	 * 
	 * @param payVO
	 * @return
	 */
	private OrderPaymentVO[] getOrderPaymentVOs(PaymentVO payVO) {
		OrderPaymentVO[] orderPayments = null;
		if (payVO == null) {
			return orderPayments;
		}
		PaymentChVO[] paybodys = payVO.getPaymentch();
		if (paybodys != null && paybodys.length > 0) {
			orderPayments = new OrderPaymentVO[paybodys.length];
			for (int i = 0; i < paybodys.length; i++) {
				PaymentChVO vo = paybodys[i];
				orderPayments[i] = new OrderPaymentVO();
				orderPayments[i].setAttributeValue(OrderPaymentVO.SHOWORDER,
						vo.getAttributeValue(OrderPaymentVO.SHOWORDER));
				orderPayments[i].setAttributeValue(OrderPaymentVO.ACCRATE,
						vo.getAttributeValue(OrderPaymentVO.ACCRATE));
				orderPayments[i].setAttributeValue(OrderPaymentVO.PREPAYMENT,
						vo.getAttributeValue(OrderPaymentVO.PREPAYMENT));
				orderPayments[i].setAttributeValue(OrderPaymentVO.EFFECTADDMONTH,
						vo.getAttributeValue(OrderPaymentVO.EFFECTADDMONTH));
				orderPayments[i].setAttributeValue(OrderPaymentVO.EFFECTMONTH,
						vo.getAttributeValue(OrderPaymentVO.EFFECTMONTH));
				orderPayments[i].setAttributeValue(OrderPaymentVO.EFFECTDATEADDDATE,
						vo.getAttributeValue(OrderPaymentVO.EFFECTDATEADDDATE));
				orderPayments[i].setAttributeValue(OrderPaymentVO.PK_PAYPERIOD,
						vo.getAttributeValue(OrderPaymentVO.PK_PAYPERIOD));
				orderPayments[i].setAttributeValue(OrderPaymentVO.PK_BALATYPE,
						vo.getAttributeValue(OrderPaymentVO.PK_BALATYPE));
				orderPayments[i].setAttributeValue(OrderPaymentVO.PK_RATE,
						vo.getAttributeValue(OrderPaymentVO.PK_RATE));
				orderPayments[i].setAttributeValue(OrderPaymentVO.PAYMENTDAY,
						vo.getAttributeValue(OrderPaymentVO.PAYMENTDAY));
				orderPayments[i].setAttributeValue(OrderPaymentVO.CHECKDATA,
						vo.getAttributeValue(OrderPaymentVO.CHECKDATA));
				orderPayments[i].setAttributeValue(OrderPaymentVO.ISDEPOSIT,
						vo.getAttributeValue(OrderPaymentVO.ISDEPOSIT));
				orderPayments[i].setAttributeValue(OrderPaymentVO.ACCOUNTDAY,
						vo.getAttributeValue(OrderPaymentVO.ACCOUNTDAY));
			}
		}
		return orderPayments;
	}

	/**
	 * 获取付款协议页签VO
	 *
	 * @param pk_payterm 付款协议档案主键
	 * @return
	 */
//  private Map<String,OrderPaymentVO[]> getOrderPaymentVOs(Set<String> pk_payterm) {
//    Map<String,OrderPaymentVO[]> paymentVOMaps = new HashMap<String, OrderPaymentVO[]>();
//    if (pk_payterm.size() == 0 ) {
//      return paymentVOMaps;
//    }
//    SuperVO[] vos = PaymentService.queryPaymentByIds(pk_payterm.toArray(new String[pk_payterm.size()]), PaymentVO.class);
//
//    for (SuperVO supvo : vos) {
//      if (paymentVOMaps.get(supvo.getAttributeValue("pk_payment").toString()) != null) {
//        continue;
//      }
//      PaymentChVO[] chvos = ((PaymentVO) supvo).getPaymentch();
//      OrderPaymentVO[] paymentVOs = new OrderPaymentVO[chvos.length];
//      for (int i = 0; i < chvos.length; i++) {
//        PaymentChVO vo = chvos[i];
//        paymentVOs[i] = new OrderPaymentVO();
//        paymentVOs[i].setAttributeValue(OrderPaymentVO.SHOWORDER,
//                vo.getAttributeValue(OrderPaymentVO.SHOWORDER));
//        paymentVOs[i].setAttributeValue(OrderPaymentVO.ACCRATE,
//                vo.getAttributeValue(OrderPaymentVO.ACCRATE));
//        paymentVOs[i].setAttributeValue(OrderPaymentVO.PREPAYMENT,
//                vo.getAttributeValue(OrderPaymentVO.PREPAYMENT));
//        paymentVOs[i].setAttributeValue(OrderPaymentVO.EFFECTADDMONTH,
//                vo.getAttributeValue(OrderPaymentVO.EFFECTADDMONTH));
//        paymentVOs[i].setAttributeValue(OrderPaymentVO.EFFECTMONTH,
//                vo.getAttributeValue(OrderPaymentVO.EFFECTMONTH));
//        paymentVOs[i].setAttributeValue(OrderPaymentVO.EFFECTDATEADDDATE,
//                vo.getAttributeValue(OrderPaymentVO.EFFECTDATEADDDATE));
//        paymentVOs[i].setAttributeValue(OrderPaymentVO.PK_PAYPERIOD,
//                vo.getAttributeValue(OrderPaymentVO.PK_PAYPERIOD));
//        paymentVOs[i].setAttributeValue(OrderPaymentVO.PK_BALATYPE,
//                vo.getAttributeValue(OrderPaymentVO.PK_BALATYPE));
//        paymentVOs[i].setAttributeValue(OrderPaymentVO.PK_RATE,
//                vo.getAttributeValue(OrderPaymentVO.PK_RATE));
//        paymentVOs[i].setAttributeValue(OrderPaymentVO.PAYMENTDAY,
//                vo.getAttributeValue(OrderPaymentVO.PAYMENTDAY));
//        paymentVOs[i].setAttributeValue(OrderPaymentVO.CHECKDATA,
//                vo.getAttributeValue(OrderPaymentVO.CHECKDATA));
//        paymentVOs[i].setAttributeValue(OrderPaymentVO.ISDEPOSIT,
//                vo.getAttributeValue(OrderPaymentVO.ISDEPOSIT));
//        paymentVOs[i].setAttributeValue(OrderPaymentVO.ACCOUNTDAY,
//                vo.getAttributeValue(OrderPaymentVO.ACCOUNTDAY));
//      }
//      paymentVOMaps.put(supvo.getAttributeValue("pk_payment").toString(), paymentVOs);
//    }
//
//    return paymentVOMaps;
//  }

	private static class OrderDataSetForCal extends VODataSetForCal {
		private OrderVO orderVO;

		public OrderDataSetForCal(CircularlyAccessibleValueObject currVO, IRelationForItems item, OrderVO orderVO) {
			super(currVO, item);
			this.orderVO = orderVO;
		}

		@Override
		public UFDate getBillDate() {
			return this.orderVO.getHVO().getDbilldate();
		}

		/** 获得原币币种 */
		@Override
		public String getCorigcurrencyid() {
			return this.orderVO.getHVO().getCorigcurrencyid();
		}

		@Override
		public boolean hasItemKey(String key) {
			if (OrderHeaderVO.CORIGCURRENCYID.equals(key)) {
				return true;
			} else if (OrderHeaderVO.DBILLDATE.equals(key)) {
				return true;
			} else {
				return super.hasItemKey(key);
			}
		}
	}
}
