

package nc.bs.ia.bill.rule.real.pub;

import nc.vo.ia.bill.entity.real.AbstractRealBill;
import nc.vo.ia.bill.entity.real.AbstractRealHeadVO;
import nc.vo.ia.bill.entity.real.AbstractRealItemVO;
import nc.vo.ia.pub.data.FieldConst;
import nc.vo.ia.pub.util.IAScaleUtil;
import nc.vo.ia.pub.util.VOValueUtil;
import nc.vo.ml.NCLangRes4VoTransl;
import nc.vo.pub.lang.UFDouble;
import nc.vo.pubapp.pattern.exception.ExceptionUtils;
import nc.vo.pubapp.pattern.log.TimeLog;
import nc.vo.pubapp.pattern.pub.MathTool;
import nc.vo.pubapp.res.NCModule;
import nc.vo.pubapp.scale.ScaleUtils;

import nc.itf.scmpub.reference.uap.bd.accesor.CurrtypeAccessor;
import nc.itf.scmpub.reference.uap.bd.accesor.MeasdocAccessor;

import nc.bs.ia.bill.pub.BillMsgUtil;

import nc.impl.pubapp.pattern.rule.IRule;

/**
 * 数据合法性校验规则(实际单据)
 * <ol>
 * <li>校验主单位,单位与换算率之间的关系是否正确
 * <li>校验单价,主数量,金额之间的关系是否正确
 * <li>校验单价,主数量,金额精度是否正确
 * </ol>
 * 
 * @since 6.0
 * @version 2010-1-14 下午02:34:25
 * @author 皮之兵
 */
public class RealPubDataValidityCheckRule<E extends AbstractRealBill>
    implements IRule<E> {
	
	private Boolean pass=true;

  @Override
  public void process(E[] bills) {
    TimeLog.logStart();
    this.checkBill(bills);
    TimeLog.info(NCLangRes4VoTransl.getNCLangRes().getStrByID("2014010_0",
        "02014010-0115")/* 校验单据信息 */); /*-=notranslate=-*/
  }

  /**
   * @param bills
   */
  private void checkBill(E[] bills) {
    for (AbstractRealBill bill : bills) {
      AbstractRealItemVO[] items = bill.getChildrenVO();
      AbstractRealHeadVO head = bill.getParentVO();
      String csrcmodulecode = bill.getParentVO().getCsrcmodulecode();
      for (AbstractRealItemVO item : items) {
        // 校验单价, 数量, 金额的精度以及它们之间的关系是否正确
        this.checkData(item, head);
        // 精度校验
//        this.checkScales(item, head);
//        if("~".equals(head.getVdef15())||"".equals(head.getVdef15())) {
//        	pass = false;
//        }
//        if(pass) {
//        // 来源采购和内部交易模块的单据不做单价金额数据关系校验
//        if (!csrcmodulecode.equals(NCModule.PO.getSystemCode())
//            && !csrcmodulecode.equals(NCModule.TO.getSystemCode())) {
//          this.checkPriceNumMny(item, head);
//        }
//        this.checkNumAstNum(item, head);
//      }
      }
    }
  }

  private void checkData(AbstractRealItemVO item, AbstractRealHeadVO head) {
    UFDouble nprice = item.getNprice();
    UFDouble nastnum = item.getNastnum();
    String vchangerate = item.getVchangerate();
    String rowno = item.getCrowno();

    if (vchangerate != null && nastnum == null) {
      String msg =
          NCLangRes4VoTransl.getNCLangRes().getStrByID("2014010_0",
              "02014010-0097", null, new String[] {
                rowno
              })/* 表体中行号为 {0} 的单据数量为空，不能保存 */;
      String billmsg = BillMsgUtil.getBillMessage(head, item);
      ExceptionUtils.wrappBusinessException(msg + billmsg);
    }

    if (nprice != null && nprice.compareTo(UFDouble.ZERO_DBL) < 0) {
      String msg =
          NCLangRes4VoTransl.getNCLangRes().getStrByID("2014010_0",
              "02014010-0098", null, new String[] {
                rowno
              })/* 表体中行号为 {0} 的单据单价为负数，不能保存 */;
      String billmsg = BillMsgUtil.getBillMessage(head, item);
      ExceptionUtils.wrappBusinessException(msg + billmsg);
    }
  }

  private void checkNumAstNum(AbstractRealItemVO item, AbstractRealHeadVO head) {
    UFDouble nnum = VOValueUtil.getUFDouble(item, FieldConst.NNUM);
    UFDouble nastnum = VOValueUtil.getUFDouble(item, FieldConst.NASTNUM);
    String vchangerate = VOValueUtil.getString(item, FieldConst.VCHANGERATE);
    String rowno = item.getCrowno();
    String cunitid = item.getCunitid();
    String castunitid = VOValueUtil.getString(item, FieldConst.CASTUNITID);
    ScaleUtils scale = ScaleUtils.getScaleUtilAtBS();
    // 数量,换算率,主数量换算关系判断
    if (nastnum != null && nastnum.compareTo(UFDouble.ZERO_DBL) != 0
        && vchangerate != null) {
      UFDouble newnum = scale.adjustNumScale(nnum, cunitid);
      UFDouble newastnum = scale.adjustNumScale(nastnum, castunitid);
      String newHsl = scale.adjustHslScale(vchangerate);
      if (!(nnum.equals(newnum) || nastnum.equals(newastnum) || vchangerate
          .equals(newHsl))) {
        StringBuffer errmsg = new StringBuffer();
        errmsg.append(NCLangRes4VoTransl.getNCLangRes().getStrByID("2014010_0",
            "02014010-0116")/* 单据出错信息如下：\n */);
        errmsg.append(NCLangRes4VoTransl.getNCLangRes().getStrByID("2014010_0",
            "02014010-0117", null, new String[] {
              MeasdocAccessor.getDocByPk(cunitid).getName().toString()
            })/* 主单位 :【{0}】\n */);
        errmsg.append(NCLangRes4VoTransl.getNCLangRes().getStrByID("2014010_0",
            "02014010-0118", null, new String[] {
              nnum.toString()
            })/* 主数量:【{0}】\n */);
        errmsg.append(NCLangRes4VoTransl.getNCLangRes().getStrByID("2014010_0",
            "02014010-0119", null, new String[] {
              newnum.toString()
            })/* 系统换算后的主数量:【{0}】\n */);
        errmsg.append(NCLangRes4VoTransl.getNCLangRes().getStrByID("2014010_0",
            "02014010-0120", null, new String[] {
              MathTool.equals(nnum, newnum) ? "Y" : "N"
            })/* 两者的大小比较 -> {0}\n */);
        errmsg.append(NCLangRes4VoTransl.getNCLangRes().getStrByID("2014010_0",
            "02014010-0121", null, new String[] {
              nastnum.toString()
            })/* 数量:【{0}】\n */);
        errmsg.append(NCLangRes4VoTransl.getNCLangRes().getStrByID("2014010_0",
            "02014010-0122", null, new String[] {
              newastnum.toString()
            })/* 系统换算后的数量:【{0}】\n */);
        errmsg.append(NCLangRes4VoTransl.getNCLangRes().getStrByID("2014010_0",
            "02014010-0123", null, new String[] {
              MathTool.equals(nastnum, newastnum) ? "Y" : "N"
            })/* 两者的大小比较 -> {0}\n */);
        errmsg.append(NCLangRes4VoTransl.getNCLangRes().getStrByID("2014010_0",
            "02014010-0124", null, new String[] {
              vchangerate
            })/* 换算率:【{0}】\n */);
        errmsg.append(NCLangRes4VoTransl.getNCLangRes().getStrByID("2014010_0",
            "02014010-0125", null, new String[] {
              newHsl
            })/* 系统换算后的换算率:【{0}】\n */);
        errmsg.append(NCLangRes4VoTransl.getNCLangRes().getStrByID("2014010_0",
            "02014010-0123", null, new String[] {
              vchangerate.equals(newHsl) ? "Y" : "N"
            })/* 两者的大小比较 -> {0}\n */);

        String msg =
            NCLangRes4VoTransl.getNCLangRes().getStrByID("2014010_0",
                "02014010-0099", null, new String[] {
                  rowno
                })/* 表体中行号为 {0} 的单据主数量,数量,换算率换算关系有误，不能保存 */;
        String billmsg = BillMsgUtil.getBillMessage(head, item);
        ExceptionUtils
            .wrappBusinessException(errmsg.toString() + msg + billmsg);
      }
    }
  }

  private void checkPriceNumMny(AbstractRealItemVO item, AbstractRealHeadVO head) {
    UFDouble nprice = VOValueUtil.getUFDouble(item, FieldConst.NPRICE);
    UFDouble nmny = item.getNmny();
    UFDouble nnum = VOValueUtil.getUFDouble(item, FieldConst.NNUM);
    String rowno = item.getCrowno();
    String currencyid = item.getCcurrencyid();
    String cunitid = item.getCunitid();
    ScaleUtils scale = ScaleUtils.getScaleUtilAtBS();
    // 单价, 主数量, 金额换算关系判断
    if (!this.isNull(nprice) && !this.isNull(nmny)) {
      UFDouble newMny = scale.adjustMnyScale(nprice.multiply(nnum), currencyid);
      UFDouble newPrice = scale.adjustPriceScale(nmny.div(nnum));
      UFDouble newNum = scale.adjustNumScale(nmny.div(nprice), cunitid);
      if (!(newMny.equals(nmny) || newPrice.equals(nprice) || newNum
          .equals(nnum))) {
        StringBuffer errmsg = new StringBuffer();
        errmsg.append(NCLangRes4VoTransl.getNCLangRes().getStrByID("2014010_0",
            "02014010-0116")/* 单据出错信息如下：\n */);
        errmsg.append(NCLangRes4VoTransl.getNCLangRes().getStrByID("2014010_0",
            "02014010-0126", null, new String[] {
              CurrtypeAccessor.getDocByPk(currencyid).getName().toString()
            })/* 币种 :【{0}】\n */);
        errmsg.append(NCLangRes4VoTransl.getNCLangRes().getStrByID("2014010_0",
            "02014010-0118", null, new String[] {
              nnum.toString()
            })/* 主数量:【{0}】\n */);
        errmsg.append(NCLangRes4VoTransl.getNCLangRes().getStrByID("2014010_0",
            "02014010-0127", null, new String[] {
              newNum.toString()
            })/* 系统计算出的主数量:【{0}】\n */);
        errmsg.append(NCLangRes4VoTransl.getNCLangRes().getStrByID("2014010_0",
            "02014010-0128", null, new String[] {
              MathTool.equals(nnum, newNum) ? "Y" : "N"
            })/* 两者的大小比较 -> {0}\n\n */);
        errmsg.append(NCLangRes4VoTransl.getNCLangRes().getStrByID("2014010_0",
            "02014010-0129", null, new String[] {
              nprice.toString()
            })/* 单价:【{0}】\n */);
        errmsg.append(NCLangRes4VoTransl.getNCLangRes().getStrByID("2014010_0",
            "02014010-0130", null, new String[] {
              newPrice.toString()
            })/* 系统计算出的单价:【{0}】\n\n */);
        errmsg.append(NCLangRes4VoTransl.getNCLangRes().getStrByID("2014010_0",
            "02014010-0123", null, new String[] {
              MathTool.equals(nprice, newPrice) ? "Y" : "N"
            })/* 两者的大小比较 -> {0}\n */);
        errmsg.append(NCLangRes4VoTransl.getNCLangRes().getStrByID("2014010_0",
            "02014010-0131", null, new String[] {
              nmny.toString()
            })/* 金额:【{0}】\n */);
        errmsg.append(NCLangRes4VoTransl.getNCLangRes().getStrByID("2014010_0",
            "02014010-0132", null, new String[] {
              newMny.toString()
            })/* 系统计算出的金额:【{0}】\n */);
        errmsg.append(NCLangRes4VoTransl.getNCLangRes().getStrByID("2014010_0",
            "02014010-0133", null, new String[] {
              MathTool.equals(nmny, newMny) ? "Y" : "N"
            })/* 两者的大小比较 -> {0}\n\n */);

        String bizmsg =
            NCLangRes4VoTransl.getNCLangRes().getStrByID("2014010_0",
                "02014010-0100", null, new String[] {
                  rowno
                })/* 表体中行号为 {0} 的单据单价, 主数量, 金额换算关系有误，不能保存 */;
        String billmsg = BillMsgUtil.getBillMessage(head, item);
        ExceptionUtils.wrappBusinessException(errmsg.toString() + bizmsg
            + billmsg);
      }
    }
  }

  private void checkScales(AbstractRealItemVO item, AbstractRealHeadVO head) {
    IAScaleUtil scale = IAScaleUtil.getScaleUtils();
    String rowno = item.getCrowno();

    UFDouble nprice = item.getNprice();
    UFDouble nnewprice = scale.adjustPriceScale(nprice);
    if (!MathTool.equals(nprice, nnewprice)) {
      StringBuffer errmsg = new StringBuffer();
      errmsg.append(NCLangRes4VoTransl.getNCLangRes().getStrByID("2014010_0",
          "02014010-0116")/* 单据出错信息如下：\n */);
      errmsg.append(NCLangRes4VoTransl.getNCLangRes().getStrByID("2014010_0",
          "02014010-0134", null, new String[] {
            String.valueOf(scale.getIACostPriceScaleDigit())
          })/* 存货核算单价精度 :【{0}】\n */);
      errmsg.append(NCLangRes4VoTransl.getNCLangRes().getStrByID("2014010_0",
          "02014010-0129", null, new String[] {
            nprice.toString()
          })/* 单价:【{0}】\n */);
      errmsg.append(NCLangRes4VoTransl.getNCLangRes().getStrByID("2014010_0",
          "02014010-0130", null, new String[] {
            nnewprice.toString()
          })/* 系统计算出的单价:【{0}】\n */);
      errmsg.append(NCLangRes4VoTransl.getNCLangRes().getStrByID("2014010_0",
          "02014010-0120", null, new String[] {
            MathTool.equals(nprice, nnewprice) ? "Y" : "N"
          })/* 两者的大小比较 -> {0}\n */);
      String msg =
          NCLangRes4VoTransl.getNCLangRes().getStrByID("2014010_0",
              "02014010-0101", null, new String[] {
                rowno
              })/* 表体中行号为 {0} 的单据单价精度与系统设置不符，不能保存 */;
      String billmsg = BillMsgUtil.getBillMessage(head, item);
      ExceptionUtils.wrappBusinessException(errmsg + msg + billmsg);
    }

    String cunitid = item.getCunitid();
    UFDouble nnum = item.getNnum();
    UFDouble nnewnum = scale.adjustNumScale(nnum, cunitid);
    if (!MathTool.equals(nnum, nnewnum)) {
      StringBuffer errmsg = new StringBuffer();
      errmsg.append(NCLangRes4VoTransl.getNCLangRes().getStrByID("2014010_0",
          "02014010-0116")/* 单据出错信息如下：\n */);
      errmsg.append(NCLangRes4VoTransl.getNCLangRes().getStrByID("2014010_0",
          "02014010-0117", null, new String[] {
            MeasdocAccessor.getDocByPk(cunitid).getName().toString()
          })/* 主单位 :【{0}】\n */);
      errmsg.append(NCLangRes4VoTransl.getNCLangRes().getStrByID("2014010_0",
          "02014010-0135", null, new String[] {
            nnum.toString()
          })/* 主数量:{0}\n */);
      errmsg.append(NCLangRes4VoTransl.getNCLangRes().getStrByID("2014010_0",
          "02014010-0136", null, new String[] {
            nnewnum.toString()
          })/* 系统计算出的主数量:{0}\n */);
      errmsg.append(NCLangRes4VoTransl.getNCLangRes().getStrByID("2014010_0",
          "02014010-0120", null, new String[] {
            MathTool.equals(nnum, nnewnum) ? "Y" : "N"
          })/* 两者的大小比较 -> {0}\n */);
      String msg =
          NCLangRes4VoTransl.getNCLangRes().getStrByID("2014010_0",
              "02014010-0102", null, new String[] {
                rowno
              })/* 表体中行号为 {0} 的单据主数量精度与系统设置不符，不能保存 */;
      String billmsg = BillMsgUtil.getBillMessage(head, item);
      ExceptionUtils.wrappBusinessException(errmsg.toString() + msg + billmsg);
    }

    String castunitid = item.getCastunitid();

    UFDouble nastnum = item.getNastnum();
    UFDouble nnewastnum = scale.adjustNumScale(nastnum, castunitid);
    if (!MathTool.equals(nastnum, nnewastnum)) {
      StringBuffer errmsg = new StringBuffer();
      errmsg.append(NCLangRes4VoTransl.getNCLangRes().getStrByID("2014010_0",
          "02014010-0116")/* 单据出错信息如下：\n */);
      errmsg.append(NCLangRes4VoTransl.getNCLangRes().getStrByID("2014010_0",
          "02014010-0137", null, new String[] {
            MeasdocAccessor.getDocByPk(castunitid).getName().toString()
          })/* 辅单位 :【{0}】\n */);
      errmsg.append(NCLangRes4VoTransl.getNCLangRes().getStrByID("2014010_0",
          "02014010-0138", null, new String[] {
            nastnum.toString()
          })/* 数量:{0}\n */);
      errmsg.append(NCLangRes4VoTransl.getNCLangRes().getStrByID("2014010_0",
          "02014010-0139", null, new String[] {
            nnewastnum.toString()
          })/* 系统计算出的数量:{0}\n */);
      errmsg.append(NCLangRes4VoTransl.getNCLangRes().getStrByID("2014010_0",
          "02014010-0120", null, new String[] {
            MathTool.equals(nastnum, nnewastnum) ? "Y" : "N"
          })/* 两者的大小比较 -> {0}\n */);
      String msg =
          NCLangRes4VoTransl.getNCLangRes().getStrByID("2014010_0",
              "02014010-0103", null, new String[] {
                rowno
              })/* 表体中行号为 {0} 的单据数量精度与系统设置不符，不能保存 */;
      String billmsg = BillMsgUtil.getBillMessage(head, item);
      ExceptionUtils.wrappBusinessException(errmsg + msg + billmsg);
    }

    String currencyid = item.getCcurrencyid();
    UFDouble nmny = item.getNmny();
    UFDouble nnewmny = scale.adjustMnyScale(nmny, currencyid);
    if (!MathTool.equals(nmny, nnewmny)) {
      StringBuffer errmsg = new StringBuffer();
      errmsg.append(NCLangRes4VoTransl.getNCLangRes().getStrByID("2014010_0",
          "02014010-0116")/* 单据出错信息如下：\n */);
      errmsg.append(NCLangRes4VoTransl.getNCLangRes().getStrByID("2014010_0",
          "02014010-0126", null, new String[] {
            CurrtypeAccessor.getDocByPk(currencyid).getName().toString()
          })/* 币种 :【{0}】\n */);
      errmsg.append(NCLangRes4VoTransl.getNCLangRes().getStrByID("2014010_0",
          "02014010-0140", null, new String[] {
            nmny.toString()
          })/* 金额:{0}\n */);
      errmsg.append(NCLangRes4VoTransl.getNCLangRes().getStrByID("2014010_0",
          "02014010-0141", null, new String[] {
            nnewmny.toString()
          })/* 系统计算出的金额:{0}\n */);
      errmsg.append(NCLangRes4VoTransl.getNCLangRes().getStrByID("2014010_0",
          "02014010-0120", null, new String[] {
            MathTool.equals(nmny, nnewmny) ? "Y" : "N"
          })/* 两者的大小比较 -> {0}\n */);
      String msg =
          NCLangRes4VoTransl.getNCLangRes().getStrByID("2014010_0",
              "02014010-0104", null, new String[] {
                rowno
              })/* 表体中行号为 {0} 的单据金额精度与系统设置不符，不能保存 */;
      String billmsg = BillMsgUtil.getBillMessage(head, item);
      ExceptionUtils.wrappBusinessException(errmsg + msg + billmsg);
    }

    UFDouble ncost = VOValueUtil.getUFDouble(item, FieldConst.NCOST);
    UFDouble nnewcost = scale.adjustMnyScale(ncost, currencyid);
    if (!MathTool.equals(ncost, nnewcost)) {
      StringBuffer errmsg = new StringBuffer();
      errmsg.append(NCLangRes4VoTransl.getNCLangRes().getStrByID("2014010_0",
          "02014010-0116")/* 单据出错信息如下：\n */);
      errmsg.append(NCLangRes4VoTransl.getNCLangRes().getStrByID("2014010_0",
          "02014010-0126", null, new String[] {
            CurrtypeAccessor.getDocByPk(currencyid).getName().toString()
          })/* 币种 :【{0}】\n */);
      errmsg.append(NCLangRes4VoTransl.getNCLangRes().getStrByID("2014010_0",
          "02014010-0142", null, new String[] {
            ncost.toString()
          })/* 费用:{0}\n */);
      errmsg.append(NCLangRes4VoTransl.getNCLangRes().getStrByID("2014010_0",
          "02014010-0143", null, new String[] {
            nnewcost.toString()
          })/* 系统计算出的费用:{0}\n */);
      errmsg.append(NCLangRes4VoTransl.getNCLangRes().getStrByID("2014010_0",
          "02014010-0120", null, new String[] {
            MathTool.equals(ncost, nnewcost) ? "Y" : "N"
          })/* 两者的大小比较 -> {0}\n */);
      String msg =
          NCLangRes4VoTransl.getNCLangRes().getStrByID("2014010_0",
              "02014010-0105", null, new String[] {
                rowno
              })/* 表体中行号为 {0} 的单据费用精度与系统设置不符，不能保存 */;
      String billmsg = BillMsgUtil.getBillMessage(head, item);
      ExceptionUtils.wrappBusinessException(errmsg + msg + billmsg);
    }
  }

  private boolean isNull(UFDouble d) {
    if (d == null || d.compareTo(UFDouble.ZERO_DBL) == 0) {
      return true;
    }
    return false;
  }

}

