package nc.bs.arap.actions;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import nc.bs.arap.bill.ArapBillPubUtil;
import nc.bs.arap.billact.BillBaseBSAction;
import nc.bs.arap.billact.IValidatorFactory;
import nc.bs.arap.billact.UpdateBatchBSAction;
import nc.bs.arap.util.ArapBillVOUtils;
import nc.bs.arap.util.ArapBusiLogUtils;
import nc.bs.arap.util.ArapVOUtils;
import nc.bs.arap.util.BillAccountCalendarUtils;
import nc.bs.arap.util.BillBankUtils;
import nc.bs.arap.util.BillStatusUtils;
import nc.bs.arap.util.BillTermUtils;
import nc.bs.arap.validator.CrossRuleCheckValidator;
import nc.bs.arap.validator.IValidatorCode;
import nc.bs.arap.validator.ValidatorFactory;
import nc.bs.businessevent.BdUpdateEvent;
import nc.bs.businessevent.BusinessEvent;
import nc.bs.businessevent.EventDispatcher;
import nc.bs.businessevent.IEventType;
import nc.bs.dao.BaseDAO;
import nc.bs.framework.common.NCLocator;
import nc.bs.pf.pub.PfDataCache;
import nc.impl.pubapp.env.BSContext;
import nc.itf.arap.fieldmap.IBillFieldGet;
import nc.itf.uap.IUAPQueryBS;
import nc.jdbc.framework.processor.BeanProcessor;
import nc.jdbc.framework.processor.ColumnProcessor;
import nc.jdbc.framework.processor.MapProcessor;
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.pay.PayBillVO;
import nc.vo.arap.payable.PayableBillItemVO;
import nc.vo.arap.pub.ArapConstant;
import nc.vo.arap.pub.BillEnumCollection;
import nc.vo.arap.pub.BillEnumCollection.BillSatus;
import nc.vo.arap.pub.BillEnumCollection.FromSystem;
import nc.vo.arap.sysinit.SysinitConst;
import nc.vo.arap.termitem.TermVO;
import nc.vo.arap.utils.StringUtil;
import nc.vo.ml.NCLangRes4VoTransl;
import nc.vo.pub.AggregatedValueObject;
import nc.vo.pub.BusinessException;
import nc.vo.pub.CircularlyAccessibleValueObject;
import nc.vo.pub.VOStatus;
import nc.vo.pub.lang.UFBoolean;
import nc.vo.pub.lang.UFDouble;

public abstract class BillUpdateBatchBSAction extends UpdateBatchBSAction {
	
	{
		validatorCode.add(IValidatorCode.CurrencyTypeValidator);
		validatorCode.add(IValidatorCode.BillStatusEditValidator);
		validatorCode.add(IValidatorCode.OriAmountNotNullValidator);
		validatorCode.add(IValidatorCode.CooperateBillAffirmValidator);
		validatorCode.add(IValidatorCode.BankAccountValidator);
		validatorCode.add(IValidatorCode.ObjectTypeValidator);
		validatorCode.add(IValidatorCode.MaxValueValidator);
	}

	public BillUpdateBatchBSAction() {
	}

	@Override
	protected IValidatorFactory getValidatorFactory() {
		ValidatorFactory vf = new ValidatorFactory();
		return vf;
	}

	@Override
	protected void doAfterFireEvent(AggregatedValueObject[] bills, AggregatedValueObject[] orginBills) throws BusinessException {

		int updateType = getUpdateType(bills, orginBills);

		if (updateType == TEMP_2_TEMP) {
		} else if (updateType == TEMP_2_SAVE) {
			EventDispatcher.fireEvent(new BusinessEvent((String) this.tmpMap.get(BillBaseBSAction.BEANID), IEventType.TYPE_INSERT_AFTER, bills));
		} else if (updateType == SAVE_2_TEMP) {
			EventDispatcher.fireEvent(new BusinessEvent((String) this.tmpMap.get(BillBaseBSAction.BEANID), IEventType.TYPE_DELETE_AFTER, orginBills));
		} else if (updateType == SAVE_2_SAVE) {
			afterEventSave2Save(bills, orginBills);
		}
	}

	/**
	 * 给期初单据重写
	 */
	protected void afterEventSave2Save(AggregatedValueObject[] bills, AggregatedValueObject[] orginBills) throws BusinessException {
		EventDispatcher.fireEvent(new BdUpdateEvent((String) this.tmpMap.get(BillBaseBSAction.BEANID), IEventType.TYPE_UPDATE_AFTER, orginBills, bills));
	}

	@Override
	protected void doBeforeFireEvent(AggregatedValueObject[] bills, AggregatedValueObject[] orginBills) throws BusinessException {

		int updateType = getUpdateType(bills, orginBills);

		// 预算控制，将单据的预算控制信息写到session
		BSContext.getInstance().setSession(ArapConstant.ARAP_TBB_ACTIONNAME, ArapConstant.ARAP_NTB_EDIT_KEY);
		if (bills != null && bills.length > 0 && ((BaseAggVO) bills[0]).isAlarmPassed()) {
			BSContext.getInstance().setSession(ArapConstant.ARAP_TBB_FLAG, ArapConstant.ARAP_TBB_NOCHECK);
		}

		if (updateType == TEMP_2_TEMP) {
		} else if (updateType == TEMP_2_SAVE) {
			EventDispatcher.fireEvent(new BusinessEvent((String) this.tmpMap.get(BillBaseBSAction.BEANID), IEventType.TYPE_INSERT_BEFORE, bills));
		} else if (updateType == SAVE_2_TEMP) {
			EventDispatcher.fireEvent(new BusinessEvent((String) this.tmpMap.get(BillBaseBSAction.BEANID), IEventType.TYPE_DELETE_BEFORE, bills));
		} else if (updateType == SAVE_2_SAVE) {
			beforeEventSave2Save(bills, orginBills);
		}
	}

	/**
	 * 给期初单据重写
	 */
	protected void beforeEventSave2Save(AggregatedValueObject[] bills, AggregatedValueObject[] orginBills) throws BusinessException {
		EventDispatcher.fireEvent(new BdUpdateEvent((String) this.tmpMap.get(BillBaseBSAction.BEANID), IEventType.TYPE_UPDATE_BEFORE, orginBills, bills));
	}

	private static int TEMP_2_TEMP = 0; // 暂存，未确认->暂存，未确认
	private static int TEMP_2_SAVE = 1; // 暂存，未确认->保存
	private static int SAVE_2_TEMP = 2; // 保存->暂存，未确认
	private static int SAVE_2_SAVE = 3; // 保存->保存

	/**
	 * @return
	 */
	public int getUpdateType(AggregatedValueObject[] bills, AggregatedValueObject[] orginBills) {
		int oldStatus = ((BaseBillVO) orginBills[0].getParentVO()).getBillstatus().intValue();
		int newStatus = ((BaseBillVO) bills[0].getParentVO()).getBillstatus().intValue();

		if (oldStatus == BillSatus.Tempeorary.VALUE.intValue() || oldStatus == BillSatus.UnComfirm.VALUE.intValue()) {
			if (newStatus == BillSatus.Tempeorary.VALUE.intValue() || newStatus == BillSatus.UnComfirm.VALUE.intValue()) {
				return TEMP_2_TEMP;
			} else {
				return TEMP_2_SAVE;
			}
		} else {
			if (newStatus == BillSatus.Tempeorary.VALUE.intValue() || newStatus == BillSatus.UnComfirm.VALUE.intValue()) {
				return SAVE_2_TEMP;
			} else {
				return SAVE_2_SAVE;
			}
		}
	}

	protected Map<String, Integer> childvostatmap = null;

	@Override
	protected void doAfterUpdate(AggregatedValueObject[] bills, AggregatedValueObject[] orginBills) throws BusinessException {
		IUAPQueryBS iuap = NCLocator.getInstance().lookup(IUAPQueryBS.class);
		String sqlterm = "select * from arap_termitem where pk_bill='"+bills[0].getParentVO().getAttributeValue("pk_payablebill")+"'";
		TermVO termVO = (TermVO) iuap.executeQuery(sqlterm, new BeanProcessor(TermVO.class));
		// 修改保存所涉及的4中状态vo
		BillTermUtils.dealBillTerm(bills, childvostatmap, orginBills);
		BillTermUtils.retBodyTermVOS(bills);
		// 单据对账对账标识码
		BillBankUtils.fillSettleBankrelated_code(bills);
		// 录入业务日志
		ArapBusiLogUtils.insertSmartBusiLogs(ArapConstant.ARAP_ACTION_EDIT, (BaseAggVO) bills[0], (BaseAggVO) orginBills[0], ArapConstant.SYS_NAME);
		String top_billid = (String) bills[0].getChildrenVO()[0].getAttributeValue("top_billid");
		if(top_billid != null) {
			//2023/10/11 YY 校验应付单金额与采购发票是否一致
			String pk_billtype = (String) bills[0].getParentVO().getAttributeValue("pk_billtype");
			//if("F1-Cxx-02".equals(type) || "D1".equals(type) || "F1-Cxx-04".equals(type) || "F1-Cxx-05".equals(type)) {
			if("F1".equals(pk_billtype)) {
				PayableBillItemVO[] payableBillItemVO = (PayableBillItemVO[]) bills[0].getChildrenVO();
				//应付总金额
				UFDouble local_notax_cr = new UFDouble(0.00);
				//应付总税额
				UFDouble local_tax_cr = new UFDouble(0.00);
				//采购发票总金额
				UFDouble znmny = new UFDouble(0.00);
				//采购发票总税额
				UFDouble zntax = new UFDouble(0.00);
				for (int j = 0; j < payableBillItemVO.length; j++) {
					String def12 = payableBillItemVO[j].getDef12();
					//没有发票号的行不进行金额校验
					if(def12 != null) {
						
						//价税合计
						UFDouble local_money_cr = new UFDouble(0.00);
						for (int x = 0; x < payableBillItemVO.length; x++) {							
							//取相应发票金额合计
							if(def12.equals(payableBillItemVO[x].getDef12())) {
								UFDouble notax_cr = payableBillItemVO[x].getLocal_notax_cr();
								UFDouble tax_cr = payableBillItemVO[x].getLocal_tax_cr();
								UFDouble money_cr = payableBillItemVO[x].getLocal_money_cr();
								local_notax_cr = local_notax_cr.add(notax_cr);
								local_tax_cr = local_tax_cr.add(tax_cr);
								local_money_cr = local_money_cr.add(money_cr);
							}
						}
						String sql1 = "select nmny,ntax,norigtaxmny from po_invoice_b where pk_invoice = (select pk_invoice from po_invoice where pk_invoice = '"+top_billid+"' and nvl(dr,0) = 0 ) and vbdef12 ='"+def12+"' and nvl(dr,0) = 0";
						Map<Object,Object> map = (Map<Object, Object>) iuap.executeQuery(sql1, new MapProcessor());
						//金额
						UFDouble nmny = new UFDouble(map.get("nmny").toString());
						//税额
						UFDouble ntax = new UFDouble(map.get("ntax").toString());
						znmny = znmny.add(nmny);
						zntax = zntax.add(ntax);
						//价税合计
						UFDouble ntotalorigmny = new UFDouble(map.get("norigtaxmny").toString());
						if(local_money_cr.compareTo(new UFDouble(ntotalorigmny)) != 0) {
						throw new BusinessException("发票号:"+def12+"与采购发票价税合计不一致！");
						}
						if(payableBillItemVO[j].getTerm() == null) {
							termVO.setPk_item(payableBillItemVO[j].getPk_payableitem());
							termVO.setLocal_money_bal(payableBillItemVO[j].getLocal_money_cr());
							termVO.setLocal_money_cr(payableBillItemVO[j].getLocal_money_cr());
							termVO.setMoney_bal(payableBillItemVO[j].getLocal_money_cr());
							termVO.setMoney_cr(payableBillItemVO[j].getLocal_money_cr());
							termVO.setOccupationmny(payableBillItemVO[j].getLocal_money_cr());
							termVO.setQuantity_bal(payableBillItemVO[j].getQuantity_cr());
							termVO.setQuantity_cr(payableBillItemVO[j].getQuantity_cr());
							List<TermVO> termList = new ArrayList<TermVO>();
							termList.add(termVO);
							(new BaseDAO()).insertVOList(termList);
							payableBillItemVO[j].setTerm(new TermVO[] {termVO});
						}
					}
				}
				//金额税额只比较总额
				if(local_notax_cr.compareTo(new UFDouble(znmny)) != 0) {
					throw new BusinessException("与采购发票金额不一致！");
				}
				if(local_tax_cr.compareTo(new UFDouble(zntax)) != 0) {
					throw new BusinessException("与采购发票税额不一致！");
				}
			}
		}
	}

	@Override
	protected void doBeforeUpdate(AggregatedValueObject[] bills, AggregatedValueObject[] orginBills) throws BusinessException {
		ArapBillPubUtil.fillTradeTypeInfo(bills);
		for (AggregatedValueObject bill : bills) {
			ArapBillPubUtil.processMoneyOnlySum(bill);
		}

		// 补充默认信息，多版本，欧盟数据..
		ArapBillVOUtils.prepareDefaultInfo(bills, true);

		int updateType = getUpdateType(bills, orginBills);

		for (AggregatedValueObject bill : bills) {
			bill.getParentVO().setStatus(VOStatus.UPDATED);
		}
		if (updateType == TEMP_2_SAVE || updateType == SAVE_2_SAVE) {
			for (AggregatedValueObject bill : bills) {
				for (CircularlyAccessibleValueObject item : bill.getChildrenVO()) {
					if (item.getStatus() != VOStatus.NEW && item.getStatus() != VOStatus.DELETED) {
						item.setStatus(VOStatus.UPDATED);
					}
				}
			}
		}
		if (updateType == TEMP_2_SAVE || updateType == SAVE_2_SAVE) {
			BillAccountCalendarUtils.setAccperiodYearMonth(bills);
		}
		checkIsCorrdBillMoneyControl(bills, orginBills);
		checkOtherSystemBill(bills, orginBills);
		// 校验交叉校验规则
		new CrossRuleCheckValidator().validate(bills);
	}

	private void checkOtherSystemBill(AggregatedValueObject[] bills, AggregatedValueObject[] orginBills) throws BusinessException {
		
		//项目管理模块
		final String STUFF_SETTLE_BILL = "4D39"; //4D39（材料结算单推应付单）
		final String EXPENSES_SETTLE_BILL = "4D83"; //4D83（费用结算单推应付单）
		final String PLAN_MONEY_BILL = "4D48"; // 4D48（进度款单推应付单）
		final String PROJECT_SETTLE_BILL = "4D50"; // 4D50（项目结算单推应付单）
		final String SELL_CONTRACT_BILL = "4D60"; // 4D60（销售合同推应收单）
		final String GATHERING_PLAN_BILL = "4D62"; // 4D62（收款计划推收款单）

		final String SELL_EXPENSES_BILL = "35"; // 35 销售费用单
		try {
			int i = 0;
			for (AggregatedValueObject bill : bills) {
				AggregatedValueObject oriBill = orginBills[i++];
				BaseBillVO billvo = (BaseBillVO) bill.getParentVO();
				BaseItemVO[] vosNew = (BaseItemVO[]) bill.getChildrenVO();

				Map<String, BaseItemVO> mapOld = new HashMap<String, BaseItemVO>();

				BaseItemVO[] vosOld = (BaseItemVO[]) oriBill.getChildrenVO();
				for (BaseItemVO vo : vosOld) {
					mapOld.put(vo.getPrimaryKey(), vo);
				}
				// 金额等第一个重要字段
				List<String> firstEditableFields = Arrays.asList(new String[] {});
				// 往来字段等第二重要字段
				List<String> secondEditableFields = Arrays.asList(new String[] { "264X", "264x" });
				// 当来源单据是销售出库,销售发票 ,签收途损时 应收单客户物料码字段不可修改
				// List<String> matCustUnEditableFields = Arrays.asList(new String[] { "4453", "4332" ,"434C"});
				// 不允许进行增行删行
				
				
				List<String> immutableRows = Arrays.asList(new String[] {
						"4A2F",
						"4A3F",
						"4A3H",
						"4A77",
						"4A87", // 周转材租入租赁结算单
						"21",
						"2201",
						"36J3",
						"4D46",
						"264X",
						SELL_EXPENSES_BILL,
						STUFF_SETTLE_BILL,
						EXPENSES_SETTLE_BILL,
						PLAN_MONEY_BILL,
						PROJECT_SETTLE_BILL,
						SELL_CONTRACT_BILL,
						GATHERING_PLAN_BILL });// 35 销售费用单 2013-04-16 @wangdongd
				List<String> arapImmutableRows = Arrays.asList(new String[] { "F0", "F1", "F2", "F3" });
				if (vosOld[0].getTop_billtype() != null) {
					if (immutableRows.contains(vosOld[0].getTop_billtype())) {
						checkBillRowsChange(bills, orginBills, false);
					} else if (arapImmutableRows.contains(vosOld[0].getTop_billtype())) {
						checkBillRowsChange(bills, orginBills, true);
					}
				}


				boolean otherSystemPushBill = ArapVOUtils.isOtherSystemPushBill(billvo, vosNew[0].getTop_billtype());
				UFBoolean sddreversalflag = UFBoolean.FALSE;
				if (billvo instanceof PayBillVO) {
					sddreversalflag = ((PayBillVO) billvo).getSddreversalflag();
					if (null == sddreversalflag) {
						sddreversalflag = UFBoolean.FALSE;
					}
				}
				if (!otherSystemPushBill && !sddreversalflag.booleanValue())
					continue;

				for (BaseItemVO vo : vosNew) {

					if (vo.getPrimaryKey() == null) {
						continue;
					}
					BaseItemVO voOld = mapOld.get(vo.getPrimaryKey());

					if (voOld == null)
						break;

					if (firstEditableFields.contains(vo.getTop_billtype())) {
						break;
					}
					String pk_billtype = vo.getPk_billtype();
					//2023/10/11 YY 应收单不校验金额
					String[] s1 = null;
					if("F1".equals(pk_billtype)) {
						s1 = new String[] {
								IBillFieldGet.OBJTYPE,
								IBillFieldGet.PK_CURRTYPE,
								IBillFieldGet.MONEY_DE,
								IBillFieldGet.PAYACCOUNT,
								IBillFieldGet.RECACCOUNT,
								IBillFieldGet.MATCUSTCODE };
					}else {
						s1 = new String[] {
								IBillFieldGet.OBJTYPE,
								IBillFieldGet.PK_CURRTYPE,
								IBillFieldGet.MONEY_DE,
								IBillFieldGet.MONEY_CR,
								IBillFieldGet.PAYACCOUNT,
								IBillFieldGet.RECACCOUNT,
								IBillFieldGet.MATCUSTCODE };
					}
					String[] s2 = new String[] {
							nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID("common", "UC000-0001935")/* @res "往来对象" */,
							nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID("common", "UC000-0001755")/* @res "币种" */,
							nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID("common", "UC000-0004112")/* @res "金额" */,
							nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID("common", "UC000-0004112")/* @res "金额" */,
							nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID("2006v61008_0", "02006v61008-0301")/* @res "付款银行账户" */,
							nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID("2006v61008_0", "02006v61008-0302")/* @res "收款银行账户" */,
							nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID("receivablebill", "2receive-000119") /* @res "客户物料码" */

					};
					int t = -1;
					for (String s : s1) {
						t++;
						// 允许补录信息 ,只允许一次修改
						if (s.equals(IBillFieldGet.PAYACCOUNT) || s.equals(IBillFieldGet.RECACCOUNT)) {
							if (voOld.getAttributeValue(s) == null || voOld.getAttributeValue(s).toString().length() != 20) {
								continue;
							}
						}
						if (s.equals(IBillFieldGet.MATCUSTCODE)) {
							if (voOld.getAttributeValue(s) == null && vo.getAttributeValue(s) == null) {
								continue;
							}
							// 销售出库--暂估应收:客户物料码携带到应收单后可编辑
							if ("434C".equals(vo.getTop_billtype()) && "23E0".equals(vo.getPk_billtype())) {
								continue;
							}
						}
						if (voOld.getAttributeValue(s) == null && vo.getAttributeValue(s) != null) {
							continue;
						}
						// 全额拒付不检查金额
						if (vo.getCommpaytype() != null
								&& (vo.getAttributeValue(s) instanceof UFDouble)
								&& (BillEnumCollection.CommissionPayType.RefuseCommPay.VALUE.equals(vo.getCommpaytype()) || BillEnumCollection.CommissionPayType.CommPayPartly.VALUE
										.equals(vo.getCommpaytype()))) {
							continue;
						}

						if (!simpEquals(voOld.getAttributeValue(s), vo.getAttributeValue(s))) {
							throw new BusinessException(nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID("2006pub_0", "02006pub-0432", null, new String[] { s2[t] })/* @res "来源于外系统的单据不能进行修改的操作！" */);
						}
					}

					if (secondEditableFields.contains(vo.getTop_billtype())) {
						break;
					}

					String[] s3 = new String[] { IBillFieldGet.CUSTOMER, IBillFieldGet.SUPPLIER, IBillFieldGet.PK_DEPTID, IBillFieldGet.PK_PSNDOC };

					String[] s4 = new String[] {
							nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID("common", "UC000-0001589")/* @res "客户" */,
							nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID("common", "UC000-0000275")/* @res "供应商" */,
							nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID("common", "UC000-0004064")/* @res "部门" */,
							nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID("2006pub_0", "02006pub-0340")
					/* @res "业务员" */};
					int[] s5 = new int[] {
							BillEnumCollection.ObjType.CUSTOMER.VALUE.intValue(),
							BillEnumCollection.ObjType.SUPPLIER.VALUE.intValue(),
							BillEnumCollection.ObjType.DEP.VALUE.intValue(),
							BillEnumCollection.ObjType.PERSON.VALUE.intValue() };

					int m = -1;
					for (int s : s5) {
						m++;
						if (!(vo.getObjtype().intValue() == s)) {
							continue;
						}

						// 允许补录信息 ,只允许一次修改
						if (voOld.getAttributeValue(s3[m]) == null || voOld.getAttributeValue(s3[m]).toString().length() != 20) {
							continue;
						}

						if (!simpEquals(voOld.getAttributeValue(s3[m]), vo.getAttributeValue(s3[m]))) {
							throw new BusinessException(nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID("2006pub_0", "02006pub-0432", null, new String[] { s4[m] })/* @res "来源于外系统的单据不能进行修改的操作！" */);
						}

					}

					// 对直接借记退回生成的付款单部分表体字段的校验
					if (!sddreversalflag.booleanValue()) {
						continue;
					}
					String[] s6 = new String[] {
							IBillFieldGet.RATE,
							IBillFieldGet.GROUPRATE,
							IBillFieldGet.GLOBALRATE,
							IBillFieldGet.LOCAL_MONEY_DE,
							IBillFieldGet.GROUPDEBIT,
							IBillFieldGet.GLOBALDEBIT,
							IBillFieldGet.SETT_ORG,
							IBillFieldGet.PK_ORG,
							IBillFieldGet.PK_BALATYPE,
							IBillFieldGet.INVOICENO };

					String[] s7 = new String[] {
							nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID("common", "2UC000-000699")/* @res "组织本币汇率" */,
							nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID("common", "2UC000-001016")/* @res "集团本币汇率" */,
							nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID("common", "2UC000-000119")/* @res "全局本币汇率" */,
							nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID("paybill", "2paybill-000013")/* @res "组织本币金额（借方）" */,
							nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID("paybill", "2paybill-000007")/* @res "集团本币金额（借方）" */,
							nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID("paybill", "2paybill-000005")/* @res "全局本币金额（借方）" */,
							nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID("common", "2UC000-000715")/* @res "结算财务组织" */,
							nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID("paybill", "2paybill-000028")/* @res "付款财务组织" */,
							nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID("common", "2UC000-000712")/* @res "结算方式" */,
							nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID("common", "2UC000-000220") /* @res "发票号" */
					};

					int n = -1;
					for (String s : s6) {
						n++;
						if (!simpEquals(voOld.getAttributeValue(s), vo.getAttributeValue(s))) {
							throw new BusinessException(nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID("2006pub_0", "02006pub-0432", null, new String[] { s7[n] })/* @res "来源于外系统的单据不能进行修改的操作！" */);
						}
					}

				}

				// 对直接借记退回生成的付款单表头字段的校验
				// 部分表头字段是由表体自动刷表头，另一部分表头字段在单据上已经设为不可编辑，对这些表头字段无需进行校验
				if (sddreversalflag.booleanValue()) {
					BaseBillVO oriBillvo = (BaseBillVO) oriBill.getParentVO();
					String[] s1 = new String[] { IBillFieldGet.EXPECTDEALDATE
					// IBillFieldGet.RECACCOUNT, IBillFieldGet.CONSIGNAGREEMENT,
					// IBillFieldGet.PK_BALATYPE, IBillFieldGet.SDDREVERSALFLAG, IBillFieldGet.REVERSALREASON,
					// IBillFieldGet.BILLMAKER, IBillFieldGet.PK_ORG, IBillFieldGet.PK_GROUP, IBillFieldGet.SETT_ORG,
					// IBillFieldGet.OBJTYPE, IBillFieldGet.CUSTOMER, IBillFieldGet.PK_CURRTYPE
					};

					String[] s2 = new String[] { nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID("paybill", "2paybill-000108") /* @res "期望处理日期" */
					// nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID("2006v61008_0","02006v61008-0302")/* @res "收款银行账户" */,
					// nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID("paybill", "2paybill-000109")/* @res "托收协议号" */,
					// nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID("common", "2UC000-000712")/* @res "结算方式" */,
					// nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID("paybill","2paybill-000111")/*@res "直接借记退回标志"*/,
					// nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID("paybill","2paybill-000112")/*@res "退回原因"*/,
					// nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID("common", "2UC000-000165")/* @res "制单人" */,
					// nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID("paybill", "2paybill-000028")/* @res "付款财务组织" */,
					// nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID("common", "2UC000-000367")/* @res "所属集团" */,
					// nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID("common", "2UC000-000715")/* @res "结算财务组织" */,
					// nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID("common", "UC000-0001935")/* @res "往来对象" */,
					// nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID("common", "UC000-0001589")/* @res "客户" */,
					// nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID("common", "UC000-0001755")/* @res "币种" */
					};

					int n = -1;
					for (String s : s1) {
						n++;
						if (!simpEquals(oriBillvo.getAttributeValue(s), billvo.getAttributeValue(s))) {
							throw new BusinessException(nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID("2006pub_0", "02006pub-0432", null, new String[] { s2[n] })/* @res "来源于外系统的单据不能进行修改的操作！" */);
						}
					}
				}
			}
		} catch (BusinessException e) {
			throw new BusinessException(e.getMessage(), e);
		}
	}

	/* 生成的单据不能增删行 */
	private void checkBillRowsChange(AggregatedValueObject[] bills, AggregatedValueObject[] orginBills, boolean isArap) throws BusinessException {
		for (int i = 0; i < bills.length; i++) {
			AggregatedValueObject oriBill = orginBills[i];
			BaseItemVO[] vosOld = (BaseItemVO[]) oriBill.getChildrenVO();
			Map<String, BaseItemVO> mapOld = new HashMap<String, BaseItemVO>();
			BaseItemVO[] vosNew = (BaseItemVO[]) bills[i].getChildrenVO();

			for (BaseItemVO vo : vosOld) {
				if (isArap) {
					if (!StringUtil.isEmpty(vo.getTop_itemid())) {
						mapOld.put(vo.getPrimaryKey(), vo);
					}
				} else {
					mapOld.put(vo.getPrimaryKey(), vo);
				}
			}
			for (BaseItemVO vo : vosNew) {
				if (vo.getPrimaryKey() == null && !isArap) {
					throw new BusinessException(NCLangRes4VoTransl.getNCLangRes().getStrByID("2006arappub0316_0", "02006arappub0316-0027", null,
							new String[] { PfDataCache.getBillType(vosOld[0].getTop_billtype()).getBilltypenameOfCurrLang() })/*@res 来自{0}的收付单据不能增加行*/);
				} else {
					if (isArap) {
						if (!StringUtil.isEmpty(vo.getTop_itemid())) {
							mapOld.remove(vo.getPrimaryKey());
						}
					} else {
						mapOld.remove(vo.getPrimaryKey());
					}
				}
			}
			if (mapOld.size() > 0) {
				throw new BusinessException(NCLangRes4VoTransl.getNCLangRes().getStrByID("2006arappub0316_0", "02006arappub0316-0026", null,
						new String[] { PfDataCache.getBillType(vosOld[0].getTop_billtype()).getBilltypenameOfCurrLang() })/*@res 来自{0}的收付单据不能删除行*/);
			}
		}
	}

	private boolean simpEquals(Object s1, Object s2) {
		if (s1 == null && s2 == null) {
			return true;
		} else if (s1 == null || s2 == null) {
			return false;
		} else {
			return s1.equals(s2);
		}
	}

	/**
	 * @param bills
	 * @param orginBills
	 *        协同单据控制总金额
	 * @throws BusinessException
	 */
	private void checkIsCorrdBillMoneyControl(AggregatedValueObject[] bills, AggregatedValueObject[] orginBills) throws BusinessException {
		try {

			int i = 0;
			for (AggregatedValueObject bill : bills) {
				AggregatedValueObject oriBill = orginBills[i++];
				BaseBillVO billVO = (BaseBillVO) bill.getParentVO();
				BaseBillVO billOriVO = (BaseBillVO) oriBill.getParentVO();
				if (billVO.getSrc_syscode() == FromSystem.XTDJ.VALUE.intValue()) {
					if (isCorrdBillMoneyControl(billVO)) {
						if (!billVO.getMoney().equals(billOriVO.getMoney())) {
							throw new BusinessException(nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID("2006pub_0", "02006pub-0434")/* @res "协同单据进行总金额控制，不能修改单据的总金额!" */);
						}

						CircularlyAccessibleValueObject[] childrenVO = bill.getChildrenVO();
						CircularlyAccessibleValueObject[] orichildrenVO = oriBill.getChildrenVO();
						for (int j = 0; j < Math.min(childrenVO.length, orichildrenVO.length); j++) {
							if (!childrenVO[j].getAttributeValue(IBillFieldGet.PK_CURRTYPE).equals(orichildrenVO[j].getAttributeValue(IBillFieldGet.PK_CURRTYPE))) {
								throw new BusinessException(nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID("2006arappub0316_0", "02006arappub0316-0029")/* @res "协同单据不能修改币种" */);
							}
						}
					}
				}
			}

		} catch (BusinessException e) {
			throw new BusinessException(e.getMessage(), e);
		}

	}

	/**
	 * @param headVO
	 * @return 协同单据是否控制总金额
	 * @throws BusinessException
	 */
	private boolean isCorrdBillMoneyControl(BaseBillVO headVO) throws BusinessException {
		UFBoolean flag = UFBoolean.FALSE;
		boolean exp = headVO.getSyscode().intValue() == FromSystem.AR.VALUE.intValue() || ArapBillPubUtil.isARSysBilltype(headVO.getPk_billtype());
		flag = SysInitQuery.getParaBoolean(headVO.getPk_org(), exp ? SysinitConst.AR18 : SysinitConst.AP18);
		return flag.booleanValue();

	}

	@Override
	protected AggregatedValueObject[] doUpdate(AggregatedValueObject[] bills, AggregatedValueObject[] orginBills) throws BusinessException {

		// 设置更新表体VO的状态 modified by liaobx 2010-8-19 20:00:00 vostatus
		// 已经缓存到childvostatmap
		childvostatmap = BillStatusUtils.enUpdateVOStauts(bills, orginBills);
		// 设置默认值, 设置CUD状态的VO的默认默认值
		beforeUpdateDefValue(bills, orginBills);
		return super.doUpdate(bills, orginBills);
	}

	protected void beforeUpdateDefValue(AggregatedValueObject[] bills, AggregatedValueObject[] orginBills) {
		BillStatusUtils.enCUDVODefVals(bills, true, orginBills);
	}

}