package nc.bs.arap.busireg;

import java.lang.reflect.Field;
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 nc.bs.arap.actions.BillDeleteBatchBSAction;
import nc.bs.arap.bill.ArapBillPubUtil;
import nc.bs.arap.util.ArapBillVOUtils;
import nc.bs.arap.util.BillMoneyVUtils;
import nc.bs.arap.util.SqlUtils;
import nc.bs.bd.util.DBAUtil;
import nc.bs.dao.BaseDAO;
import nc.bs.framework.common.NCLocator;
import nc.bs.pf.pub.PfDataCache;
import nc.bs.pub.pf.PfUtilTools;
import nc.impl.pubapp.pattern.data.bill.BillDelete;
import nc.impl.pubapp.pattern.data.bill.BillOperator;
import nc.itf.arap.billconfer.IBConferMapQryService;
import nc.itf.arap.billconfer.IBConferMapService;
import nc.itf.arap.billconfer.IBillConferQueryService;
import nc.itf.arap.fieldmap.IBillFieldGet;
import nc.pubitf.arap.bill.IArapBillPubQueryService;
import nc.pubitf.para.SysInitQuery;
import nc.vo.arap.basebill.BaseAggVO;
import nc.vo.arap.basebill.BaseBillVO;
import nc.vo.arap.basebill.BaseItemVO;
import nc.vo.arap.billconfer.BCMiddleVO;
import nc.vo.arap.billconfer.BCParamVO;
import nc.vo.arap.billconfer.BcMapVO;
import nc.vo.arap.billconfer.BillconferVO;
import nc.vo.arap.pub.ArapBillTypeInfo;
import nc.vo.arap.pub.ArapConstant;
import nc.vo.arap.pub.BillEnumCollection;
import nc.vo.arap.pub.IArapBilltypeInfo;
import nc.vo.arap.pub.BillEnumCollection.BillCooperate;
import nc.vo.arap.pub.BillEnumCollection.BillSatus;
import nc.vo.arap.pub.BillEnumCollection.FromSystem;
import nc.vo.arap.pub.BillEnumCollection.ObjType;
import nc.vo.arap.sysinit.SysinitConst;
import nc.vo.fipub.exception.ExceptionHandler;
import nc.vo.jcom.lang.StringUtil;
import nc.vo.ml.NCLangRes4VoTransl;
import nc.vo.org.OrgVO;
import nc.vo.pub.AggregatedValueObject;
import nc.vo.pub.BeanHelper;
import nc.vo.pub.BusinessException;
import nc.vo.pub.BusinessRuntimeException;
import nc.vo.pub.CircularlyAccessibleValueObject;
import nc.vo.pub.billtype.BilltypeVO;
import nc.vo.pub.lang.UFBoolean;
import nc.vo.pub.lang.UFDate;
import nc.vo.pub.lang.UFDouble;

import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;

/**
 * @author liaobx at 2011-3-4
 *
 */
public final class BConferUtils {

	private static final String ARAPCONFERNUMFLAG = "ARAP_";

	private static String getCoordContent(BaseBillVO headVO) throws BusinessException {
		return SysInitQuery.getParaString(headVO.getPk_org(), headVO.getSyscode().intValue() == FromSystem.AR.VALUE.intValue() ? SysinitConst.AR16 : SysinitConst.AP16);
	}

	public static boolean canSave(BaseAggVO bill,boolean isdelete) throws BusinessException {
		BaseBillVO headVO = (BaseBillVO) bill.getParentVO();
		boolean equals = SysinitConst.SYSCODE_SAVE.equals(getCoordContent(headVO));
		equals = isAlsoGenrat(bill, equals,isdelete);
		return equals;
	}
	public static boolean canDelete(BaseBillVO headVO) throws BusinessException {
		boolean coordflag = headVO.getCoordflag() != null ? headVO.getCoordflag().equals(Integer.valueOf(1)) : false ;
		boolean billstatus = BillEnumCollection.BillSatus.Save.VALUE.equals(headVO.getBillstatus()) ||
		BillEnumCollection.BillSatus.Tempeorary.VALUE.equals(headVO.getBillstatus())||
		BillEnumCollection.BillSatus.UnComfirm.VALUE.equals(headVO.getBillstatus());
		return coordflag && billstatus;
	}

	/**
	 * @param headVO
	 * @param equals
	 * @return
	 * @throws BusinessException
	 */
	private static boolean isAlsoGenrat(BaseAggVO bill, boolean equals,boolean isdelete) throws BusinessException {
		// 根据协同号确认是否已经，被协同过
		BaseItemVO[] items = bill.getItems();
		if(isdelete){
			BaseBillVO headVO = (BaseBillVO) bill.getParentVO();
			return equals && (null == headVO.getCoordflag() || headVO.getCoordflag().intValue() == BillCooperate.NOSUER.VALUE.intValue());
		}
		return equals && (items == null||items.length==0?false:StringUtil.isEmpty(items[0].getConfernum()));
	}

	public static boolean canEffect(BaseAggVO bill,boolean isdelete) throws BusinessException {
		BaseBillVO headVO = (BaseBillVO) bill.getParentVO();
		boolean equals = SysinitConst.SYSCODE_EFFECT.equals(getCoordContent(headVO));
		equals = isAlsoGenrat(bill, equals,isdelete);
		return equals;
	}

	private static boolean isAlsoGenrat(BaseBillVO headVO) throws BusinessException {
		// V61  AR17，AP19，协同单据能否再协同不再使用!
//		if (headVO.getSyscode() == null) {
//			throw new BusinessRuntimeException(nc.vo.ml.NCLangRes4VoTransl.getNCLangRes()
//					.getStrByID("common", "UC000-0000814")/* @res "单据号" */
//					+ headVO.getBillno()
//					+ nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID("2006pub_0",
//							"02006pub-0301")/* @res "syscode 不能为空" */);
//		}
//
//		boolean exp = headVO.getSyscode().intValue() == FromSystem.AR.VALUE.intValue();
//		UFBoolean flag = SysInitQuery.getParaBoolean(headVO.getPk_org(), exp ? SysinitConst.AR17 : SysinitConst.AP19);
//		return flag.booleanValue();
		return false;
	}

	/** 协同生成的单据 */
	public static boolean isCoorBill(BaseBillVO headVO) {
		return headVO.getSrc_syscode().intValue() == FromSystem.XTDJ.VALUE.intValue();
	}

	public static boolean canRedoCoord(BaseBillVO headVO) throws BusinessException {
		return SysInitQuery.getParaBoolean(headVO.getPk_org(), headVO.getSyscode().intValue() == FromSystem.AR.VALUE.intValue() ? SysinitConst.AR16 : SysinitConst.AP16).booleanValue();
	}

	/** 获取客商主键 */
	public static String[] getCusSups(BaseAggVO[] bills) {
		List<String> cusSup = new ArrayList<String>();
		for (BaseAggVO bill : bills) {
			BaseBillVO headVO = bill.getHeadVO();

			if (ObjType.CUSTOMER.VALUE == headVO.getObjtype()) {
				cusSup.add(headVO.getCustomer());
			} else if (ObjType.SUPPLIER.VALUE == headVO.getObjtype()) {
				cusSup.add(headVO.getSupplier());
			}
		}
		return cusSup.toArray(new String[0]);
	}

	public void save(BaseAggVO srcbill) throws BusinessException {
		save(srcbill,false);
	}

	public void save(BaseAggVO srcbill,boolean isupdate) throws BusinessException {
		if (srcbill == null || srcbill.getHeadVO() == null || ArrayUtils.isEmpty(srcbill.getItems())) {
			return;
		}

		// 是协同单据 而且 不能再协同
		if (isCoorBill(srcbill.getHeadVO()) && !isAlsoGenrat(srcbill.getHeadVO())) {
			return;
		}

		// 如果表体中有协同号就不能再协同了
		if(hasConferNum(srcbill,isupdate)){
			return ;
		}
		// 如果上游单据 不协同
		// 36J3 内部转账单
		// 5F 内部结算清
		// 264X 报销单
		if(isFromOtherSystem(srcbill)){
			return ;
		}
		IBillConferQueryService qryservice = NCLocator.getInstance().lookup(IBillConferQueryService.class);
		BillconferVO[] confers = qryservice.queryVOByBothTrade(srcbill.getHeadVO().getPk_tradetype(), srcbill.getHeadVO().getPk_group());
		
		if(ArrayUtils.isEmpty(confers)){
			return;
		}
		
		BaseAggVO conferBill = getConferVO(srcbill);
		if(conferBill == null){
			return;
		}
		BaseAggVO[] destVOs = generateItemVO(conferBill, conferBill.getItems());
		if (ArrayUtils.isEmpty(destVOs)) {
			return;
		}

		if(isCoorBill(srcbill.getHeadVO())){
			BaseItemVO[] items = srcbill.getItems();
			String topBillid = items[0].getTop_billid();
			String topBilltype = items[0].getTop_billtype();
			BaseAggVO[] vos = NCLocator.getInstance().lookup(ArapBillTypeInfo.getInstance(topBilltype).getBillQueryService()).findBillByPrimaryKey(new String[]{topBillid});
			if(vos!=null && vos.length!=0){
				if(vos[0].getHeadVO().getPk_org().equals(destVOs[0].getHeadVO().getPk_org())){
					return;
				}
			}
		}
		
		

		befInstVal(destVOs);
		save(destVOs);
		saveBcMap(destVOs, srcbill.getHeadVO().getPk_billtype(), srcbill.getHeadVO().getPrimaryKey());
	}

	private BaseAggVO getConferVO(BaseAggVO srcbill) {
		BaseItemVO[] items = srcbill.getItems();
		List<CircularlyAccessibleValueObject> conferList = new ArrayList<CircularlyAccessibleValueObject>();
		for (CircularlyAccessibleValueObject child : items) {
			UFDouble money = (UFDouble) child.getAttributeValue(IBillFieldGet.MONEY_DE);
			if (money == null || money.equals(UFDouble.ZERO_DBL)) {
				money = (UFDouble) child.getAttributeValue(IBillFieldGet.MONEY_CR);
			}
			if (money != null && !money.equals(UFDouble.ZERO_DBL)) { 
				// 只有金额不为0时，才能协同；金额为0且税额不为0，不能协同
				conferList.add((BaseItemVO) child);
			}
		}
		if(conferList.size() == 0){
			return null;
		}
		BaseAggVO conferBill = (BaseAggVO) srcbill.clone();
		conferBill.setChildrenVO(conferList.toArray(new BaseItemVO[0]));
		return conferBill;
	}

	private boolean isFromOtherSystem(BaseAggVO srcbill) {
		// 36J3 内部转账单
		// 5F 内部结算清
		// 264X 报销单
		boolean isOtherSys =false;
		if(srcbill == null || ArrayUtils.isEmpty(srcbill.getItems())){
			return isOtherSys;
		}

		String topBilltype = srcbill.getItems()[0].getTop_billtype();
		if(StringUtils.isEmpty(topBilltype)){
			return isOtherSys;
		}

		if(topBilltype.equalsIgnoreCase("36J3") ||
				topBilltype.equalsIgnoreCase("5F")||
				topBilltype.startsWith("264")){
			isOtherSys = true;
		}

		return isOtherSys;
	}

	private boolean hasConferNum(BaseAggVO srcbill, boolean isupdate) {
		for(BaseItemVO item : srcbill.getItems()) {
			if(StringUtils.isNotEmpty(item.getConfernum())){
				if(!item.getConfernum().startsWith(ARAPCONFERNUMFLAG)){
					return true;
				}else if(!isupdate){
					return true;
				}
			}
		}
		return false;
	}

	/**
	 * @param pk_billtype
	 * @param headPK
	 */
	private void saveBcMap(AggregatedValueObject[] destVOs, String pk_billtype, String headPK) throws BusinessException {
		for(AggregatedValueObject destVO:destVOs){
			BcMapVO bcMapVO = new BcMapVO();
			BaseAggVO baseAggVO = (BaseAggVO)destVO;
			bcMapVO.setSrc_billtype(pk_billtype);
			bcMapVO.setSrc_billid(headPK);
			bcMapVO.setDest_billtype(baseAggVO.getItems()[0].getPk_billtype());
			bcMapVO.setDest_billid(baseAggVO.getHeadVO().getPrimaryKey());
			bcMapVO.setReceiver(baseAggVO.getConferReceiver());
			bcMapVO.setMessage(baseAggVO.getConferMessageInfo());
			NCLocator.getInstance().lookup(IBConferMapService.class).insertBcMapVO(bcMapVO);
		}
	}

	/** 通知用户 */
	@SuppressWarnings("unused")
	private void notifyUsers() {

	}

	/** 保存 */
	private void save(AggregatedValueObject[] destVOs) throws BusinessException {
		new BillOperator<BaseAggVO>().insert((BaseAggVO[]) destVOs);
	}

	/**
	 * 设置一些默认值
	 *
	 * @param confVo
	 */
	private void befInstVal(AggregatedValueObject[] destVOs) {
		for (AggregatedValueObject vo : destVOs) {
			BaseAggVO bill = (BaseAggVO) vo;
			bill.getHeadVO().setCoordflag(BillCooperate.NOSUER.VALUE);
			bill.getHeadVO().setBillstatus(BillSatus.UnComfirm.VALUE);
			bill.getHeadVO().setSrc_syscode(FromSystem.XTDJ.VALUE);
			UFDate billdate = bill.getHeadVO().getBilldate();
			if (billdate == null) {
				billdate = new UFDate();
				bill.getHeadVO().setBusidate(billdate);
				bill.getHeadVO().setBilldate(billdate);
			} else {
				bill.getHeadVO().setBusidate(billdate);
			}
			if (bill.getHeadVO().getBillperiod() != null && bill.getHeadVO().getBillperiod().length() == 10) {
				bill.getHeadVO().setBillperiod(bill.getHeadVO().getBillperiod().substring(5, 7));
			}
			for (BaseItemVO bvo : bill.getItems()) {
				bvo.setCoordflag(Integer.valueOf(1));
				if (billdate == null) {
					billdate = new UFDate();
					bvo.setBusidate(billdate);
					bvo.setBilldate(billdate);
				} else {
					bvo.setBusidate(billdate);
				}

				// 组织级别档案“部门”，“业务员“直接清空
//				bvo.setPk_deptid(null);
//				bvo.setPk_deptid_v(null);
				bvo.setPk_psndoc(null);
			}
			ArapBillPubUtil.processMoney(vo);
		}
	}

	enum ConferStatus {
		/** 含有唯一单据协同 */
		HAS_REAL_CONFER(1),
		/** 含有通用的单据协同 sourceorg 为 '~' */
		HAS_GENERAL_CONFER(2),
		/** 没有单据协同 */
		NONE_CONFER(0);
		public final Integer VALUE;

		ConferStatus(int value) {
			VALUE = value;
		}
	}

	private BaseAggVO[] generateItemVO(BaseAggVO srcbill, BaseItemVO[] items) throws BusinessException {
		// 内部客商, 客户/供应商的 ID可能相同
		Set<String> customers = new HashSet<String>();
		Set<String> suppliers = new HashSet<String>();
		IBillConferQueryService qryservice = NCLocator.getInstance().lookup(IBillConferQueryService.class);
		String orgname = null;

		Map<String, BCMiddleVO> map = new HashMap<String, BCMiddleVO>();
		// 供应商客户对应表体的PK
		Map<String, String> cusupMItemPk = new HashMap<String, String>();
		for (BaseItemVO vo : items) {
			BCParamVO paramVO = new BCParamVO();
			paramVO.setBusitype(srcbill.getHeadVO().getPk_busitype());
			paramVO.setSrcorg(vo.getPk_org());
			paramVO.setSrcTradetype(vo.getPk_tradetype());

			if (ObjType.CUSTOMER.VALUE.equals(vo.getObjtype())) {
				paramVO.setObjType(ObjType.SUPPLIER);
				if (!customers.contains(vo.getCustomer())) {
					customers.add(vo.getCustomer());
					cusupMItemPk.put(vo.getCustomer(), vo.getPrimaryKey());
					paramVO.setSrcCustsup(vo.getCustomer());
					map.put(vo.getPrimaryKey(), qryservice.queryBillConfer(paramVO));
				} else {
					String key = cusupMItemPk.get(vo.getCustomer());
					map.put(vo.getPrimaryKey(), map.get(key));
				}

			} else if (ObjType.SUPPLIER.VALUE.equals(vo.getObjtype())) {
				paramVO.setObjType(ObjType.CUSTOMER);
				if (!suppliers.contains(vo.getSupplier())) {
					suppliers.add(vo.getSupplier());
					cusupMItemPk.put(vo.getSupplier(), vo.getPrimaryKey());
					paramVO.setSrcCustsup(vo.getSupplier());
					map.put(vo.getPrimaryKey(), qryservice.queryBillConfer(paramVO));
				} else {
					String key = cusupMItemPk.get(vo.getSupplier());
					map.put(vo.getPrimaryKey(), map.get(key));
				}
			}
		}
		Map<String, BaseAggVO> voMap = new HashMap<String, BaseAggVO>();

		// 复制聚合VO上的属性
		Map<String, Object> billValMap = new HashMap<String, Object>();
		Field[] declaredFields = srcbill.getClass().getDeclaredFields();
		for (Field field : declaredFields) {
			billValMap.put(field.getName(), BeanHelper.getProperty(srcbill, field.getName()));
		}

		BaseAggVO[] bills = new BaseAggVO[0];

		// billconfersql
		Set<String> sqls= new HashSet<String>();
		if (map.size() > 0) {
			String targetbill = map.values().toArray(new BCMiddleVO[] {})[0].getTargetbill();

			bills = new BaseAggVO[items.length];
			for (int i = 0; i < items.length; i++) {

				BCMiddleVO bcMiddleVO = map.get(items[i].getPrimaryKey());
				if (null == bcMiddleVO) {
					continue;
				}

				targetbill = bcMiddleVO.getTargetbill();
				String targetorg = bcMiddleVO.getTargetorg();

				if (StringUtils.isEmpty(targetbill) || StringUtils.isEmpty(targetorg)) {
					continue;
				}

				try {
					BaseAggVO newInstance = srcbill.getClass().newInstance();
					newInstance.setParentVO((CircularlyAccessibleValueObject) srcbill.getParentVO().clone());
					// 设置聚合VO的属性
					for (Map.Entry<String, Object> entry : billValMap.entrySet()) {
						BeanHelper.setProperty(newInstance, entry.getKey(), billValMap.get(entry.getKey()));
					}

					newInstance.setChildrenVO(new BaseItemVO[] {(BaseItemVO) items[i].clone()});
					bills[i] = newInstance;

				} catch (Exception e) {
					ExceptionHandler.handleException(e);
				}

				bills[i] = (BaseAggVO) PfUtilTools.runChangeData(items[i].getPk_billtype(), targetbill, bills[i]);
				String pk_billtype = (String) bills[i].getParentVO().getAttributeValue(IBillFieldGet.PK_BILLTYPE);
				
				if(pk_billtype.equals(IBillFieldGet.F0) || pk_billtype.equals(IBillFieldGet.F2)){
					bills[i].getParentVO().setAttributeValue(IBillFieldGet.CUSTOMER, bcMiddleVO.getCustsup());
					bills[i].getParentVO().setAttributeValue(IBillFieldGet.ORDERCUBASDOC, bcMiddleVO.getCustsup());
					bills[i].getParentVO().setAttributeValue(IBillFieldGet.SUPPLIER, null);
				}else{
					bills[i].getParentVO().setAttributeValue(IBillFieldGet.SUPPLIER, bcMiddleVO.getCustsup());
					bills[i].getParentVO().setAttributeValue(IBillFieldGet.CUSTOMER, null);
				}
				
				bills[i].getParentVO().setAttributeValue(IBillFieldGet.PK_ORG, targetorg);
				bills[i].getParentVO().setAttributeValue(IBillFieldGet.SETT_ORG, targetorg);


				String[] headClearFields = new String[] {
						IBillFieldGet.PK_BUSITYPE,
						IBillFieldGet.PK_ORG_V,
						IBillFieldGet.SETT_ORG_V,
						IBillFieldGet.PK_PCORG, 
						IBillFieldGet.PK_PCORG_V, 
						IBillFieldGet.CHECKELEMENT, 
				};

				for(String clear:headClearFields){
					bills[i].getParentVO().setAttributeValue(clear,null);
				}

//				String[] bodyClearFields = new String[] { IBillFieldGet.PK_DEPTID_V, IBillFieldGet.PK_DEPTID,
//						IBillFieldGet.PK_PCORG, IBillFieldGet.CHECKELEMENT, IBillFieldGet.PK_PSNDOC };
				
				String[] bodyClearFields = new String[] { IBillFieldGet.PK_PCORG, IBillFieldGet.CHECKELEMENT, IBillFieldGet.PK_PSNDOC };

				for (CircularlyAccessibleValueObject item : bills[i].getChildrenVO()) {
					item.setAttributeValue(IBillFieldGet.PK_ORG, targetorg);
					item.setAttributeValue(IBillFieldGet.SETT_ORG, targetorg);
					
					if(pk_billtype.equals(IBillFieldGet.F0) || pk_billtype.equals(IBillFieldGet.F2)){
						item.setAttributeValue(IBillFieldGet.CUSTOMER, bcMiddleVO.getCustsup());
						item.setAttributeValue(IBillFieldGet.ORDERCUBASDOC, bcMiddleVO.getCustsup());
						item.setAttributeValue(IBillFieldGet.SUPPLIER, null);
					}else{
						item.setAttributeValue(IBillFieldGet.CUSTOMER, null);
						item.setAttributeValue(IBillFieldGet.SUPPLIER, bcMiddleVO.getCustsup());
					}
					
					
					item.setAttributeValue(IBillFieldGet.OBJTYPE, bcMiddleVO.getObjtype());


					for(String clear:bodyClearFields){
						item.setAttributeValue(clear,null);
					}

					if(StringUtils.isNotEmpty(bcMiddleVO.getReceiver())){
						bills[i].setConferReceiver(bcMiddleVO.getReceiver());
					}
					if (voMap.containsKey(targetorg)) {
						BaseAggVO baseAggVO = voMap.get(targetorg);
						BaseItemVO[] childrenVO = (BaseItemVO[]) baseAggVO.getChildrenVO();
						BaseItemVO[] childrenVO2 = new BaseItemVO[childrenVO.length + 1];
						for (int j = 0; j < childrenVO2.length; j++) {
							if (j == childrenVO2.length - 1) {
								childrenVO2[j] = (BaseItemVO) item;
							} else {
								childrenVO2[j] = childrenVO[j];
							}
						}
						bills[i].setChildrenVO(childrenVO2);
						voMap.put(targetorg, bills[i]);
					}
					else {
						voMap.put(targetorg, bills[i]);
					}

					// 自制协同时结算号全局唯一。结算号的编码生成规则：接收方组织编码（客商对应的财务组织）+发起方的单据号编码
					// 接收方组织编码（客商对应的财务组织）集团唯一， 所以去接收方组织PK（客商对应的财务组织）
					String billconfernum = ARAPCONFERNUMFLAG + targetorg + "_" + items[i].getBillno();
					((BaseItemVO)item).setConfernum(billconfernum);

					sqls.add(buildConferNumSql((BaseItemVO) item , srcbill
						.getItems()[0],true) );
				}
			}

			bills = new BaseAggVO[voMap.values().size()];
			bills = voMap.values().toArray(bills);

			for (BaseAggVO sbill : bills) {
				BillMoneyVUtils.sumBodyToHead(sbill.getHeadVO(), sbill.getItems());

				if(orgname==null){
					orgname=NCLocator.getInstance().lookup(nc.pubitf.org.IOrgUnitPubService.class).getOrgs(new String[]{srcbill.getHeadVO().getPk_org()}, new String[]{OrgVO.PK_ORG,OrgVO.NAME})[0].getName();
				}
				if(StringUtils.isNotEmpty(sbill.getConferReceiver())){
					String scomment = ((BaseItemVO)sbill.getChildrenVO()[0]).getScomment();
					sbill.setConferMessageInfo(NCLangRes4VoTransl
							.getNCLangRes().getStrByID(
								"2006arappub0316_0",
								"02006arappub0316-0011",
								null,
								new String[] {orgname,sbill.getHeadVO().getMoney().setScale(4, UFDouble.ROUND_HALF_UP).toString(), scomment }));
				}
			}
		}
		//协同单据财务组织期初期间启用校验
		conferBillBillDateValidate(bills);
		
		// 补充默认信息，多版本，欧盟数据
		ArapBillVOUtils.prepareDefaultInfo(bills);

		if (sqls.size() > 0) {
			DBAUtil.execBatchSql(sqls.toArray(new String[] {}));
		}
		
		ArapBillPubUtil.resetDestVODoc(bills);
		return bills;
	}

	// 生成更新来源单据协同好的sql语句
	@SuppressWarnings("deprecation")
	private String buildConferNumSql(BaseItemVO item, BaseItemVO srcItemVO, boolean isGenaration) {
		if(StringUtils.isEmpty(item.getConfernum()) || StringUtils.isEmpty(srcItemVO.getTableName())) {
			throw new IllegalArgumentException(nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID("2006arappub0316_0","02006arappub0316-0014")/*@res "协同号 和tableName 不能为空"*/);
		}
		StringBuffer sql = new StringBuffer();
		sql.append("update ").append(srcItemVO.getTableName()).append(" set ");
		sql.append(IBillFieldGet.CONFERNUM);
		if (isGenaration) {
			sql.append(" = '").append(item.getConfernum()).append("' ");
		} else {
			sql.append(" = null ");
		}
		sql.append("where ").append(srcItemVO.getPKFieldName()).append(" = '");
		sql.append(item.getTop_itemid()).append("';");
		return sql.toString();
	}

	private String buildTopBillConferNumSql(BaseAggVO[] bills) throws BusinessException {
		Set<String> pks = new HashSet<String>();
		String topBilltype = null;
		for (BaseAggVO bill : bills) {
			for (BaseItemVO item : bill.getItems()) {
				if (StringUtils.isNotEmpty(item.getConfernum()) && StringUtils.isNotEmpty(item.getTop_billtype())) {
					topBilltype = item.getTop_billtype();
					pks.add(item.getTop_itemid());
				}
			}
		}

		if (topBilltype == null)
			return null;

		StringBuffer sql = new StringBuffer();
		String tableName = null;
		String pkFieldName = null;
		if (StringUtils.isNotEmpty(topBilltype)) {
			BilltypeVO billType = PfDataCache.getBillType(topBilltype);
			if (billType == null || billType.getSystemcode() == null
					|| (!billType.getSystemcode().equalsIgnoreCase("arap")
							&& !billType.getSystemcode().equalsIgnoreCase("ar") && !billType
							.getSystemcode().equalsIgnoreCase("ap"))) {
				return null;
			}

			IArapBilltypeInfo instance = ArapBillTypeInfo.getInstance(topBilltype);
			tableName = instance == null ? null : instance.getTableNameItem();
			pkFieldName = instance == null ? null : instance.getTablePrimaryKeyItem();

		}
		if (tableName == null || pkFieldName == null) {
			throw new BusinessRuntimeException(nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID("2006arappub0316_0","02006arappub0316-0015")/*@res "上游单据类型不能为空"*/);
		}

		sql.append("update ").append(tableName).append(" set ");
		sql.append(IBillFieldGet.CONFERNUM);
		sql.append(" = null ");
		sql.append(" where ");
		sql.append(SqlUtils.getInStr(pkFieldName, pks.toArray(new String[] {})));
		return sql.toString();
	}
	public void reGeneratBConfer(BaseAggVO[] bills) throws BusinessException {
		// 查询单据
		BcMapVO[] bcmaps = NCLocator.getInstance().lookup(IBConferMapQryService.class).queryBCMapByIDAndBType(bills[0].getHeadVO().getPrimaryKey(), bills[0].getHeadVO().getPk_billtype());

		if (bcmaps != null) {
			for (BcMapVO bcmap : bcmaps) {
				if (null != bcmap && StringUtils.isNotEmpty(bcmap.getDest_billid()) && StringUtils.isNotEmpty(bcmap.getDest_billtype())) {
					BaseAggVO[] aggvo = NCLocator.getInstance().lookup(IArapBillPubQueryService.class).findBillByPrimaryKey(new String[] { bcmap.getDest_billid() }, new String[] { bcmap.getDest_billtype() });
					if (!(ArrayUtils.isEmpty(aggvo))) {
						for(BaseAggVO agg:aggvo){
							BaseBillVO parentVO = (BaseBillVO) agg.getParentVO();
							if(parentVO.getBillstatus().intValue()!=BillEnumCollection.BillSatus.UnComfirm.VALUE.intValue()){
								throw new BusinessException(nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID("2006v61020_0","02006v61020-0120")/*
								 * @res
								 * "协同单据已经确认，上游不能反操作!"
								 */);
							}
						}

						new BillDelete<BaseAggVO>().delete(aggvo);
						NCLocator.getInstance().lookup(IBConferMapService.class).deleteByPks(new String[] { bills[0].getHeadVO().getPrimaryKey() }, bills[0].getHeadVO().getPk_billtype());
					}
				}
			}
		}

		// 重新生成协同单据
		new BConferUtils().save(bills[0], true);
	}

	public void deleteBillConfer(BaseAggVO bill) throws BusinessException {
		IBConferMapQryService bcqrys = NCLocator.getInstance().lookup(IBConferMapQryService.class);
		BcMapVO[] bcmaps = bcqrys.queryBCMapByIDAndBType(bill.getHeadVO().getPrimaryKey(), bill.getHeadVO().getPk_billtype());

		if (bcmaps != null) {
			for (BcMapVO bcmap : bcmaps) {
				if (null != bcmap && StringUtils.isNotEmpty(bcmap.getDest_billid()) && StringUtils.isNotEmpty(bcmap.getDest_billtype())) {

					IArapBillPubQueryService qrys = NCLocator.getInstance().lookup(IArapBillPubQueryService.class);
					BaseAggVO[] aggvo = qrys.findBillByPrimaryKey(new String[] { bcmap.getDest_billid() }, new String[] { bcmap.getDest_billtype() });
					deleteBill(bill, aggvo);

					IBConferMapService bcms = NCLocator.getInstance().lookup(IBConferMapService.class);
					bcms.deleteByPks(new String[] { bill.getHeadVO().getPrimaryKey() }, bill.getHeadVO().getPk_billtype());
				}
			}
		}


	}

	public void clearBillConferNum(BaseAggVO[] bills) throws BusinessException {
		// 删除来源协同的协同号
		String buildTopBillConferNumSql = buildTopBillConferNumSql(bills);
		if (buildTopBillConferNumSql != null) {
			DBAUtil.execBatchSql(new String[] { buildTopBillConferNumSql });
		}
	}

	/** [ONLY For] 协同来源单据 删除协同单据 */
	private void deleteBill(BaseAggVO srcbill, BaseAggVO[] billconfers) throws BusinessException {
		for (BaseAggVO billconfer : billconfers) {
			// 已经确认
			if (billconfer.getHeadVO().getBillstatus() != BillSatus.UnComfirm.VALUE.intValue()) {
				ExceptionHandler.createAndThrowException(nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID("2006v61020_0","02006v61020-0120")/*
						 * @res
						 * "协同单据已经确认，上游不能反操作!"
						 */);
				
			}
			// 修改与保存统一 jianglx要求 
//			nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID("2006pub_0", "02006pub-0305")/*
//			 * @res
//			 * "协同单据"
//			 */+ billconfer.getHeadVO().getBillno()
//			 + nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID("2006pub_0", "02006pub-0306")/*
//			  * @res
//			  * "已经被确认不能被删除"
//			  */
			// 没有界面
		}
		if (!ArrayUtils.isEmpty(billconfers)) {
			// 删除来源协同的协同号
			Set<String> sqls = new HashSet<String>();
			for (int i = 0; i < billconfers.length; i++) {
				for (BaseItemVO itemVO : billconfers[i].getItems()) {
					sqls.add(buildConferNumSql(itemVO, srcbill.getItems()[0], false));
				}
			}

			new BillDeleteBatchBSAction().deleteVOs(billconfers);
			String[] keys = new String[billconfers.length];
			List<String> keys2 = new ArrayList<String>();
			for (int i = 0; i < billconfers.length; i++) {
				keys[i] = billconfers[i].getHeadVO().getPrimaryKey();
				for (BaseItemVO baseitem : billconfers[i].getItems()) {
					keys2.add(baseitem.getPrimaryKey());
				}
			}
			BaseDAO baseDAO = new BaseDAO();
			baseDAO.deleteByPKs(billconfers[0].getHeadVO().getClass(), keys);
			baseDAO.deleteByPKs(billconfers[0].getItems()[0].getClass(), keys2.toArray(new String[0]));

			if (sqls.size() > 0) {
				DBAUtil.execBatchSql(sqls.toArray(new String[] {}));
			}
		}

	}
	
	private void conferBillBillDateValidate(BaseAggVO[] bills){
		if(bills != null && bills.length > 0){
			if(bills[0].getParentVO().getAttributeValue(IBillFieldGet.PK_ORG) != null && !StringUtil.isEmpty((String)bills[0].getParentVO().getAttributeValue(IBillFieldGet.PK_ORG))){
				UFDate billDate = (UFDate)bills[0].getParentVO().getAttributeValue(IBillFieldGet.BILLDATE);
				String destOrg = (String)bills[0].getParentVO().getAttributeValue(IBillFieldGet.PK_ORG);
				String syscode = getModuleCode((Integer)bills[0].getParentVO().getAttributeValue(IBillFieldGet.SYSCODE));
				UFDate calendar = null;
				try {					
					if(bills[0].getParentVO().getAttributeValue(IBillFieldGet.ISINIT)!=null && ((UFBoolean)bills[0].getParentVO().getAttributeValue(IBillFieldGet.ISINIT)).booleanValue()){
						calendar = ArapBillPubUtil.getArapCreateDate(syscode.equals(ArapConstant.AR_MODULE_ID),destOrg);
					}else{
						calendar = ArapBillPubUtil.getOrgModuleperiodDate(syscode.equals(ArapConstant.AR_MODULE_ID),destOrg);
					}
				} catch (nc.vo.pubapp.pattern.exception.CarrierRuntimeException e) {
					throw new BusinessRuntimeException(nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID("2006arappub0316_0","02006arappub0316-0067")/*@res "协同单据财务组织未设置期初期间！"*/);
				}
				if(null == calendar){
					throw new BusinessRuntimeException(nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID("2006arappub0316_0","02006arappub0316-0067")/*@res "协同单据财务组织未设置期初期间！"*/);
				}
				if(bills[0].getParentVO().getAttributeValue(IBillFieldGet.ISINIT)!=null && ((UFBoolean)bills[0].getParentVO().getAttributeValue(IBillFieldGet.ISINIT)).booleanValue()){//期初
					if(billDate.after(calendar)){
						throw new BusinessRuntimeException(nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID("2006arappub0316_0","02006arappub0316-0068")/*@res "即将生成的协同期初单据,单据日期必须在启用日期之前！"*/);
					}
				}else{
					if(!billDate.after(calendar)){
						throw new BusinessRuntimeException(nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID("2006arappub0316_0","02006arappub0316-0069")/*@res "协同单据的单据日期必须在账套启用日期之后！"*/);
					}
				}
			}
		}
	}
	
	public String getModuleCode(Integer syscode) {
		String codes = null;

		if (syscode == 0)// 应收系统
		{
			codes = "2006";
		} else if (syscode == 1)// 应付系统
		{
			codes = "2008";
		}
		return codes;
	}

}
