package com.engine.htsc.payment.service.impl;

import com.engine.core.impl.Service;
import com.engine.htsc.common.utils.DoubleUtil;
import com.engine.htsc.payment.log.PaymentLogger;
import com.engine.htsc.payment.log.PaymentLoggerFactory;
import com.engine.htsc.payment.pojo.PaDetail;
import com.engine.htsc.payment.pojo.PreApproval;
import com.engine.htsc.payment.service.PreApprovalService;
import com.engine.htsc.payment.util.CommonAPI;
import com.engine.htsc.payment.util.LuhnUtil;
import com.engine.htsc.payment.util.StringUtil;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import weaver.conn.RecordSet;
import weaver.general.Util;
import weaver.workflow.mode.FieldInfo;
import weaver.workflow.workflow.WorkflowComInfo;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class PreApprovalServiceImpl extends Service implements PreApprovalService {

  private final Log log = LogFactory.getLog(this.getClass());

  private final PaymentLogger logger = PaymentLoggerFactory.getLogger(PreApprovalServiceImpl.class);

  /**
   * 报销流程
   */
  private final String[] bx_workflow = new String[]{"zbtybx", "fzjgtybx","lhtybx","xgtybx"};
  /**
   * 差旅流程
   */
  private final String[] cl_workflow = new String[]{"fzjgclbx","zbclbx","clbx","xgclbx"};
  /**
   * 付款流程
   */
  private final String[] fk_workflow = new String[]{"zbtyfk", "zbitfk", "zbghfk", "fzjgtyfk","fyft","jjhtyfk","xgtyfk","lhtyfk","zgtyfk"};

  /**
   * 科目id
   */
  private final String[] km = new String[]{"8601020301", "8601020302", "8601020101", "8601020601", "8601050101", "8601050102",
      "8701010501", "8701010201", "8701010101", "8701010401", "8701010301", "87010203", "87010202", "87010201"};

  /**
   * 科目id对应表单id
   */
  private final String[] fjfield = new String[]{"fjfymxd", "fjfymxd", "fjfymxd", "fjhytz", "fjggxgt", "fjxcptp",
      "fjzcysrkd", "fjzcysrkd", "fjzcysrkd", "fjzcysrkd", "fjzcysrkd", "fjgcfksqd", "fjgcfksqd", "fjgcfksqd"};

  private String tablename = "";
  private String rid = "";
  private String mainid = "";
  private String workflowid = "";
  private List<String> tips;
  private String unNumberNew = "";

  @Override
  public List<PreApproval> getPreAplInfos(String requestid) throws Exception {
    String tableName = "";
    String unNumber = "";
    rid = requestid;
    String sql = "SELECT t2.UNNUMBER,t3.TABLENAME,t1.REQUESTID,t1.WORKFLOWID FROM WORKFLOW_REQUESTBASE t1\n" +
        "LEFT JOIN WORKFLOW_BASE t2\n" +
        "ON t1.WORKFLOWID = t2.ID\n" +
        "LEFT JOIN WORKFLOW_BILL t3\n" +
        "ON t2.FORMID = t3.ID \n" +
        "WHERE t2.ISVALID = 1 AND t1.REQUESTID = ?";
    RecordSet rs = new RecordSet();
    rs.executeQuery(sql, requestid);
    if (rs.next()) {
      tableName = Util.null2String(rs.getString("TABLENAME"));
      unNumber = Util.null2String(rs.getString("UNNUMBER"));
      tablename = tableName;
      unNumberNew = unNumber;
      workflowid = Util.null2String(rs.getString("WORKFLOWID"));
    }
    sql = "SELECT ID FROM " + tablename + " WHERE REQUESTID = ?";
    rs.executeQuery(sql, requestid);
    if (rs.next()) {
      mainid = Util.null2String(rs.getString("ID"));
    }
    log.info(String.format("requestid: %s; tableName: %s; unNumber:%s", requestid, tableName, unNumber));
    List<PreApproval> model = new ArrayList<>();
    if (Arrays.asList(fk_workflow).contains(unNumber)) {
      log.info("判断为付款流程");
      //发票重复校验
      model.add(checkInvoices(requestid));
      //基金会通用付款不进行合同校验
      if (!"jjhtyfk".equals(unNumberNew)){
        //合同信息校验
        model.add(checkContract(requestid));
      }
      //表单金额控制校验
      model.add(checkMoney(requestid));
      //其他信息校验
      model.add(checkOthers(requestid));
    } else if (Arrays.asList(bx_workflow).contains(unNumber)) {
      log.info("判断为报销流程");
      //发票重复校验
      model.add(checkInvoicesBx(requestid));
      //表单金额控制校验
      model.add(checkMoneyBx(requestid));
      //其他校验
      model.add(checkOthersBx(requestid));
    } else if (Arrays.asList(cl_workflow).contains(unNumber)) {
      log.info("判断为差旅流程");
      //发票重复校验
      model.add(checkInvoicesCl(requestid));
      //表单金额控制校验
      model.add(checkMoneyCl(requestid));
      //其他校验
      model.add(checkOthersCl(requestid));
    } else {
      throw new IllegalArgumentException("unNumber:" + unNumber + ", 在付款和报销流程中没有匹配");
    }

    return model;
  }

  public PreApproval checkContractBx(String requestid) throws Exception {
    Validate.notEmpty(requestid, "requestid 为空, 退出checkContract方法");
    PreApproval preApproval = new PreApproval();
    preApproval.setType("2");
    preApproval.setLabel("合同");
    List<PaDetail> details = new ArrayList<>();
    //合同金额校验
    details.add(buildAccountCheck("1"));

    preApproval.setDetails(details);
    return preApproval;
  }

  public PreApproval checkContract(String requestid) throws Exception {
    Validate.notEmpty(requestid, "requestid 为空, 退出checkContract方法");
    PreApproval preApproval = new PreApproval();
    preApproval.setType("2");
    preApproval.setLabel("合同");
    List<PaDetail> details = new ArrayList<>();
    //合同金额校验
    details.add(buildAccountCheck("0"));
    //合同总额金额校验
    details.add(buildContractAmountCheck());
    //已付金额校验
    details.add(buildAlreadyPayCheck());
    //银行信息校验
//    details.add(buildBankInfoCheck());
    //银行卡号校验
//    details.add(buildBankNumCheck());
    preApproval.setDetails(details);
    return preApproval;
  }

  public PreApproval checkMoney(String requestid) throws Exception {
    Validate.notEmpty(requestid, "requestid 为空, 退出checkContract方法");
    PreApproval preApproval = new PreApproval();
    preApproval.setType("3");
    preApproval.setLabel("表单金额控制");
    List<PaDetail> details = new ArrayList<>();
    //银行信息校验
    details.add(buildBankInfoCheck());
    //银行卡号校验
    details.add(buildBankNumCheck());
    //发票合计金额与费用合计金额校验
    details.add(buildFpOrFyHjCheck());
    preApproval.setDetails(details);
    return preApproval;
  }

  public PreApproval checkMoneyBx(String requestid) throws Exception {
    Validate.notEmpty(requestid, "requestid 为空, 退出checkContract方法");
    PreApproval preApproval = new PreApproval();
    preApproval.setType("3");
    preApproval.setLabel("表单金额控制");
    List<PaDetail> details = new ArrayList<>();
    //银行信息校验
    details.add(buildBankInfoCheck());
    //银行卡号校验
    details.add(buildBankNumCheck());
    //发票合计金额与费用合计金额校验
    details.add(buildFpOrFyHjCheck());
    preApproval.setDetails(details);
    return preApproval;
  }

  public PreApproval checkMoneyCl(String requestid) throws Exception {
    Validate.notEmpty(requestid, "requestid 为空, 退出checkContract方法");
    PreApproval preApproval = new PreApproval();
    preApproval.setType("3");
    preApproval.setLabel("表单金额控制");
    List<PaDetail> details = new ArrayList<>();
    //银行信息校验
    details.add(buildBankInfoCheckCl());
    //银行卡号校验
    details.add(buildBankNumCheckCl());
    //发票合计金额与费用合计金额校验
    details.add(buildFpOrFyHjCheckCl());
    preApproval.setDetails(details);
    return preApproval;
  }

  public PreApproval checkInvoicesBx(String requestid) throws Exception {
    Validate.notEmpty(tablename, "tablename 为空, 退出checkInvoices方法");
    Validate.notEmpty(requestid, "requestid 为空, 退出checkInvoices方法");

    PreApproval preApproval = new PreApproval();
    preApproval.setType("1");
    preApproval.setLabel("发票");

    List<String> fps = new ArrayList<>();
    List<String> yzs = new ArrayList<>();
    String sql = "SELECT t1.FPHM,t1.FPDM,t1.YZ FROM " + tablename + "_DT5 t1\n" +
        "LEFT JOIN " + tablename + " t2\n" +
        "ON t1.MAINID = t2.ID \n" +
        "WHERE t2.REQUESTID = ?";
    RecordSet rs = new RecordSet();
    rs.executeQuery(sql, requestid);
    while (rs.next()) {
      String dm = Util.null2String(rs.getString("FPDM"));
      String hm = Util.null2String(rs.getString("FPHM"));
      String yz = Util.null2String(rs.getString("YZ"));
      fps.add(String.join("@", dm, hm));
      yzs.add(String.join("@", dm, hm, StringUtils.isEmpty(yz) ? "0" : yz));
    }
    sql = "SELECT t1.FPHM,t1.FPDM,t2.id FROM " + tablename + "_DT6 t1\n" +
        "LEFT JOIN " + tablename + " t2\n" +
        "ON t1.MAINID = t2.ID \n" +
        "WHERE t2.REQUESTID = ?";
    rs.executeQuery(sql, requestid);
    while (rs.next()) {
      String dm = Util.null2String(rs.getString("FPDM"));
      String hm = Util.null2String(rs.getString("FPHM"));
      fps.add(String.join("@", dm, hm));

      mainid = Util.null2String(rs.getString("id"));
    }
//    Map<String, Long> countMap = fps.stream().collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
//    List<String> disFps = countMap.keySet().stream().filter(key -> countMap.get(key) > 1).distinct().collect(Collectors.toList());
//    log.info("重复发票: " + disFps);
    List<PaDetail> details = new ArrayList<>();
    details.add(buildFpCf(fps));
    details.add(buildFpYz(yzs));
//    details.add(buildFkPjGx(requestid));
    preApproval.setDetails(details);

    return preApproval;

  }

  public PreApproval checkInvoicesCl(String requestid) throws Exception {
    Validate.notEmpty(tablename, "tablename 为空, 退出checkInvoices方法");
    Validate.notEmpty(requestid, "requestid 为空, 退出checkInvoices方法");

    PreApproval preApproval = new PreApproval();
    preApproval.setType("1");
    preApproval.setLabel("发票");

    List<String> fps = new ArrayList<>();
    List<String> yzs = new ArrayList<>();
    String sql = "SELECT t1.FPHM,t1.FPDM,t1.YZ FROM " + tablename + "_DT4 t1\n" +
            "LEFT JOIN " + tablename + " t2\n" +
            "ON t1.MAINID = t2.ID \n" +
            "WHERE t2.REQUESTID = ?";
    RecordSet rs = new RecordSet();
    rs.executeQuery(sql, requestid);
    while (rs.next()) {
      String dm = Util.null2String(rs.getString("FPDM"));
      String hm = Util.null2String(rs.getString("FPHM"));
      String yz = Util.null2String(rs.getString("YZ"));
      fps.add(String.join("@", dm, hm));
      yzs.add(String.join("@", dm, hm, StringUtils.isEmpty(yz) ? "0" : yz));
    }
    sql = "SELECT t1.FPHM,t1.FPDM,t2.id FROM " + tablename + "_DT5 t1\n" +
            "LEFT JOIN " + tablename + " t2\n" +
            "ON t1.MAINID = t2.ID \n" +
            "WHERE t2.REQUESTID = ?";
    rs.executeQuery(sql, requestid);
    while (rs.next()) {
      String dm = Util.null2String(rs.getString("FPDM"));
      String hm = Util.null2String(rs.getString("FPHM"));
      fps.add(String.join("@", dm, hm));

    }
    sql = "SELECT t1.FPHM,t1.FPDM,t2.id FROM " + tablename + "_DT6 t1\n" +
            "LEFT JOIN " + tablename + " t2\n" +
            "ON t1.MAINID = t2.ID \n" +
            "WHERE t2.REQUESTID = ?";
    rs.executeQuery(sql, requestid);
    while (rs.next()) {
      String dm = Util.null2String(rs.getString("FPDM"));
      String hm = Util.null2String(rs.getString("FPHM"));
      fps.add(String.join("@", dm, hm));

      mainid = Util.null2String(rs.getString("id"));
    }
//    Map<String, Long> countMap = fps.stream().collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
//    List<String> disFps = countMap.keySet().stream().filter(key -> countMap.get(key) > 1).distinct().collect(Collectors.toList());
//    log.info("重复发票: " + disFps);
    List<PaDetail> details = new ArrayList<>();
    details.add(buildFpCf(fps));
    details.add(buildFpYz(yzs));
//    details.add(buildFkPjGx(requestid));
    preApproval.setDetails(details);

    return preApproval;

  }

  public PreApproval checkInvoices(String requestid) throws Exception {
    Validate.notEmpty(tablename, "tablename 为空, 退出checkInvoices方法");
    Validate.notEmpty(requestid, "requestid 为空, 退出checkInvoices方法");

    PreApproval preApproval = new PreApproval();
    preApproval.setType("1");
    preApproval.setLabel("发票");

    List<String> fps = new ArrayList<>();
    List<String> yzs = new ArrayList<>();
    String sql = "SELECT t1.FPHM,t1.FPDM,t1.YZ FROM " + tablename + "_DT5 t1\n" +
        "LEFT JOIN " + tablename + " t2\n" +
        "ON t1.MAINID = t2.ID \n" +
        "WHERE t2.REQUESTID = ?";
    RecordSet rs = new RecordSet();
    rs.executeQuery(sql, requestid);
    while (rs.next()) {
      String dm = Util.null2String(rs.getString("FPDM"));
      String hm = Util.null2String(rs.getString("FPHM"));
      String yz = Util.null2String(rs.getString("YZ"));
      fps.add(String.join("@", dm, hm));
      yzs.add(String.join("@", dm, hm, StringUtils.isEmpty(yz) ? "0" : yz));
    }
    sql = "SELECT t1.FPHM,t1.FPDM,t2.id FROM " + tablename + "_DT6 t1\n" +
        "LEFT JOIN " + tablename + " t2\n" +
        "ON t1.MAINID = t2.ID \n" +
        "WHERE t2.REQUESTID = ?";
    rs.executeQuery(sql, requestid);
    while (rs.next()) {
      String dm = Util.null2String(rs.getString("FPDM"));
      String hm = Util.null2String(rs.getString("FPHM"));
      fps.add(String.join("@", dm, hm));

      mainid = Util.null2String(rs.getString("id"));
    }
//    Map<String, Long> countMap = fps.stream().collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
//    List<String> disFps = countMap.keySet().stream().filter(key -> countMap.get(key) > 1).distinct().collect(Collectors.toList());
//    log.info("重复发票: " + disFps);
    List<PaDetail> details = new ArrayList<>();
    details.add(buildFpCf(fps));
    details.add(buildFpYz(yzs));
    if(!"xgtyfk".equals(unNumberNew)){
      details.add(buildFkPjGx(requestid));
    }
    preApproval.setDetails(details);
    return preApproval;

  }

  public PreApproval checkOthersBx(String requestid) throws Exception {
    Validate.notEmpty(requestid, "requestid 为空, 退出checkOthersBx方法");
    PreApproval preApproval = new PreApproval();
    preApproval.setType("4");
    preApproval.setLabel("其他");
    List<PaDetail> details = new ArrayList<>();
    //只针对总部和分支的通用报销流程
    if(!"lhtybx".equals(unNumberNew) && !"xgtybx".equals(unNumberNew) ){
      details.add(buildAttachmentCheck());
      details.add(buildAutoFillFormCheck());
    }
    details.add(buildHrmCheck());
    details.add(buildNeedValueCheckBx());
    preApproval.setDetails(details);
    return preApproval;
  }

  public PreApproval checkOthersCl(String requestid) throws Exception {
    Validate.notEmpty(requestid, "requestid 为空, 退出checkOthersBx方法");
    PreApproval preApproval = new PreApproval();
    preApproval.setType("4");
    preApproval.setLabel("其他");
    List<PaDetail> details = new ArrayList<>();
    details.add(buildHrmCheckCl());
    details.add(buildNeedValueCheckCl());
    preApproval.setDetails(details);
    return preApproval;
  }

  public PreApproval checkOthers(String requestid) throws Exception {
    Validate.notEmpty(requestid, "requestid 为空, 退出checkOthers方法");
    PreApproval preApproval = new PreApproval();
    preApproval.setType("4");
    preApproval.setLabel("其他");
    List<PaDetail> details = new ArrayList<>();
    //基金会通用付款不进行合同对手方校验和预算科目校验
    if("jjhtyfk".equals(unNumberNew)){
      details.add(buildAttachmentCheck());
      details.add(buildHistoryPayCheck());
      details.add(buildNeedValueCheck());
    }else if ("lhtyfk".equals(unNumberNew) ||"xgtyfk".equals(unNumberNew)||"zgtyfk".equals(unNumberNew)){
      //联合通用付款不进行科目与附件信息校验和自动填单预算科目校验
      details.add(buildInvoicedEqualsContractCheck());
      details.add(buildHistoryPayCheck());
      details.add(buildNeedValueCheck());
    }else if("zbghfk".equals(unNumberNew) ||"xgtybx".equals(unNumberNew)){
      details.add(buildAutoFillFormCheck());
      details.add(buildInvoicedEqualsContractCheck());
      details.add(buildHistoryPayCheck());
      details.add(buildNeedValueCheck());
    }else{
      details.add(buildAttachmentCheck());
      details.add(buildAutoFillFormCheck());
      details.add(buildInvoicedEqualsContractCheck());
      details.add(buildHistoryPayCheck());
      details.add(buildNeedValueCheck());
    }
    preApproval.setDetails(details);
    return preApproval;
  }



  /**
   * 发票重复校验
   *
   * @param fps
   * @return
   */
  private PaDetail buildFpCf(List<String> fps) throws Exception {
    PaDetail pd = new PaDetail();
    pd.setInfo("发票重复校验");
    if (CollectionUtils.isEmpty(fps)) {
      pd.setCheck(true);
      pd.setTips(String.join(",", "未提供发票"));
      return pd;
    }

    List<String> dTips = new ArrayList<>();
    String sql = "SELECT t2.REQUESTID,t2.REQUESTMARK,t1.FPDM,t1.FPHM FROM UF_PJXXGL t1\n" +
        "LEFT JOIN WORKFLOW_REQUESTBASE t2\n" +
        "ON t1.REQUESTID = t2.REQUESTID \n" +
        "WHERE t1.FPDM = ? AND t1.FPHM = ?";
    RecordSet rs = new RecordSet();
    //获取当前流程编号
    RecordSet sqlFindRemark = new RecordSet();
    fps.stream().distinct().forEach(item -> {
      if (!"@".equals(item)){
        if (!item.startsWith("@") && !item.endsWith("@")){
          rs.executeQuery(sql, item.split("@")[0], item.split("@")[1]);
          String remarkNew = "";
          sqlFindRemark.executeQuery("SELECT REQUESTMARK FROM WORKFLOW_REQUESTBASE WHERE REQUESTID  = ?",rid);
          if (sqlFindRemark.next()){
            remarkNew = Util.null2String(sqlFindRemark.getString("REQUESTMARK"));
          }
          while (rs.next()) {
            if(!rs.getString("REQUESTMARK").equals(remarkNew)){
              dTips.add("发票" + rs.getString("FPHM")
                      + "(" + rs.getString("FPDM")
                      + ")已被流程" + rs.getString("REQUESTMARK") + "占用，请核实发票信息");
            }
          }
        }
      }
    });
    pd.setCheck(CollectionUtils.isEmpty(dTips));
    pd.setTips(String.join(",", dTips));
    return pd;
  }

  /**
   * 发票验真校验
   *
   * @param yzs
   * @return
   */
  private PaDetail buildFpYz(List<String> yzs) throws Exception {
    PaDetail pd = new PaDetail();
    pd.setInfo("发票验真校验");
    if (CollectionUtils.isEmpty(yzs)) {
      pd.setCheck(true);
      pd.setTips(String.join(",", "未提供验真发票"));
      return pd;
    }
    List<String> dTips = new ArrayList<>();
    yzs.stream().distinct().forEach(item -> {
      if (!"1".equals(item.split("@")[2])) {
        dTips.add("发票" + item.split("@")[0] + "(" + item.split("@")[1] + ")验真未通过，请核实发票信息");
      }
    });
    pd.setCheck(CollectionUtils.isEmpty(dTips));
    pd.setTips(String.join(",", dTips));
    return pd;
  }

  /**
   * 是否提供发票和付款信息校验
   *
   * @param requestid
   * @return
   */
  private PaDetail buildFkPjGx(String requestid) throws Exception {
    List<String> dTips = new ArrayList<>();
    String sql = "SELECT DJZS,SFXFKHTGFP FROM " + tablename + " WHERE REQUESTID = ?";
    RecordSet rs = new RecordSet();
    rs.executeQuery(sql, requestid);
    if (rs.next()) {
      String djzs = Util.null2String(rs.getString("DJZS"));
      String sfxfkhtgfp = Util.null2String(rs.getString("SFXFKHTGFP"));
      if (("0".equals(djzs) || "".equals(djzs)) && "1".equals(sfxfkhtgfp)) { //0为是
        dTips.add("请确认本次付款申请是否为“先付款后提供发票”");
      }
    }

    PaDetail pd = new PaDetail();
    pd.setInfo("是否提供发票校验");
    pd.setCheck(CollectionUtils.isEmpty(dTips));
    pd.setTips(String.join(",", dTips));
    return pd;
  }

  /**
   * 4、合同本次申请金额（仅付款）=预算合计（报销合计）=支付合计才能提交；
   * 适用范围：见“提示信息”标注
   * 控制：不允许提交流程
   * 提示信息：
   * （付款流程，且有合同信息，当上述3种金额不相等时）请核实：本期申请金额=预算合计=支付合计
   * （付款流程，且无合同信息，当上述3种金额不相等时）请核实：预算合计=支付合计
   * （报销流程，当上述3种金额不相等时）请核实：报销合计=支付合计
   *
   * @param type 类型 0:付款, 1:报销
   * @return
   */
  public PaDetail buildAccountCheck(String type) throws Exception {
    List<String> tips = new ArrayList<>();
    RecordSet rs = new RecordSet();
    DecimalFormat df = new DecimalFormat("0.00");
    if ("0".equals(type)) {
      String sql = "SELECT t1.hjxxjeitxmf,t1.hjxxjezfmx,t2.bqzfje FROM " + tablename + " t1\n" +
          "LEFT JOIN " + tablename + "_DT4 t2\n" +
          "ON t1.ID = t2.MAINID\n" +
          "WHERE t1.REQUESTID = ?";
      String bqzfje = "";
      String hjxxjeitxmf = "";
      String hjxxjezfmx = "";
      rs.executeQuery(sql, rid);
      if (rs.next()) {
        bqzfje = Util.null2String(rs.getString("bqzfje")); //合同本期金额
        hjxxjeitxmf = df.format(Double.parseDouble(Util.null2String(rs.getString("hjxxjeitxmf"))));
        hjxxjezfmx = df.format(Double.parseDouble(Util.null2String(rs.getString("hjxxjezfmx"))));
      }
      if (StringUtils.isNotEmpty(bqzfje)) {
        bqzfje = df.format(Double.parseDouble(bqzfje));
        //存在合同信息
        if (!(new BigDecimal(hjxxjeitxmf).equals(new BigDecimal(hjxxjezfmx)) &&
                new BigDecimal(bqzfje).equals(new BigDecimal(hjxxjeitxmf)))) {
          tips.add("请核实：本期申请金额=预算合计=支付合计");
        }
      } else {
        if (!new BigDecimal(hjxxjeitxmf).equals(new BigDecimal(hjxxjezfmx))) {
          tips.add("请核实：预算合计=支付合计");
        }
      }
    } else if ("1".equals(type)) {
      String sql = "SELECT hjxxjeitxmf,hjxxjezfmx FROM " + tablename + " WHERE REQUESTID =?";
      rs.executeQuery(sql, rid);
      String hjxxjeitxmf = "";
      String hjxxjezfmx = "";
      if (rs.next()) {
        hjxxjeitxmf = df.format(Double.parseDouble(Util.null2String(rs.getString("hjxxjeitxmf"))));
        hjxxjezfmx = df.format(Double.parseDouble(Util.null2String(rs.getString("hjxxjezfmx"))));
      }
      if (!new BigDecimal(hjxxjeitxmf).equals(new BigDecimal(hjxxjezfmx))) {
        tips.add("请核实：预算合计=支付合计");
      }
    } else {
      throw new IllegalArgumentException("buildAccountCheck没有指定type类型");
    }

    PaDetail pd = new PaDetail();
    pd.setInfo("合同及小计金额校验");
    pd.setCheck(CollectionUtils.isEmpty(tips));
    pd.setTips(String.join(",", tips));
    return pd;
  }

  /**
   * 5、合同总额=本次申请金额+已付金额+剩余可用金额
   * 适用范围：付款流程
   * 控制：仅提示，允许发起流程
   * 提示信息：
   * （当合同总额≠本次申请金额+已付金额+剩余可用金额时）请核实“合同金额=本期申请金额+已付金额+剩余可用金额”
   *
   * @return
   */
  public PaDetail buildContractAmountCheck() throws Exception {
    List<String> tips = new ArrayList<>();
    String sql = "SELECT htze,bqzfje,yfjebhbq,wfjebhbq FROM " + tablename + "_DT4 fmd WHERE MAINID = ?";
    String htze = "";
    String bqzfje = "";
    String yfjebhbq = "";
    String wfjebhbq = "";
    RecordSet rs = new RecordSet();
    rs.executeQuery(sql, mainid);
    if (rs.next()) {
      htze = Util.null2String(rs.getString("htze")); //合同总额
      bqzfje = Util.null2String(rs.getString("bqzfje")); //本次申请金额
      yfjebhbq = Util.null2String(rs.getString("yfjebhbq")); //已付金额
      wfjebhbq = Util.null2String(rs.getString("wfjebhbq")); //剩余可用金额
      BigDecimal allMoney = DoubleUtil.add(DoubleUtil.add(blank2Zero(bqzfje), blank2Zero(yfjebhbq), 2).toString(),
              blank2Zero(wfjebhbq), 2);//本次申请金额+已付金额+剩余可用金额
      DecimalFormat df = new DecimalFormat("0.00");
      BigDecimal htzeNew = new BigDecimal(df.format(Double.valueOf(blank2Zero(htze))));
      if ("0".equals(htze) || !htzeNew.equals(allMoney) ){
        tips.add("请核实“合同金额=本期申请金额+已付金额+剩余可用金额”");
      }
    }

    PaDetail pd = new PaDetail();
    pd.setInfo("合同总额金额校验");
    pd.setCheck(CollectionUtils.isEmpty(tips));
    pd.setTips(String.join(",", tips));
    return pd;
  }

  /**
   * 6、已付金额=关联合同中已付金额合计
   * 适用范围：付款流程
   * 控制：仅提示，允许发起流程
   * 提示信息：
   * （关联合同时，将合同已付金额多存一个备用字段，提交的时候，将表单上的合同已付金额与备用字段对比。当金额不一致时）请核实合同已付金额
   */
  private PaDetail buildAlreadyPayCheck() throws Exception {
    List<String> tips = new ArrayList<>();
    String sql = "SELECT yfjeby,yfjebhbq FROM " + tablename + "_DT4 WHERE MAINID = ?";
    RecordSet rs = new RecordSet();
    rs.executeQuery(sql, mainid);
    String yfjeby = "";
    String yfjebhbq = "";
    if (rs.next()) {
      DecimalFormat df = new DecimalFormat("0.00");
      yfjeby = df.format(Double.parseDouble(Util.null2s(rs.getString("yfjeby"),"0.00"))); //备用支付金额
      yfjebhbq = df.format(Double.parseDouble(Util.null2s(rs.getString("yfjebhbq"),"0.00")));
      if (!new BigDecimal(yfjeby).equals(new BigDecimal(yfjebhbq))) {
        tips.add("请核实合同已付金额");
      }
    }

    PaDetail pd = new PaDetail();
    pd.setInfo("已付金额校验");
    pd.setCheck(CollectionUtils.isEmpty(tips));
    pd.setTips(String.join(",", tips));
    return pd;
  }

  /**
   * 7、当银行支付金额不为0时，银行卡信息必填。当银行支付金额为0，且现金支付金额不为0时，银行卡信息不必填；
   * 适用范围：付款流程、报销流程、差旅报销
   * 控制：不允许提交
   * 提示信息：
   * （当银行支付金额不为0，银行卡信息未填写时）请填写银行卡信息
   *
   * @return
   */
  public PaDetail buildBankInfoCheck() throws Exception {
    List<String> tips = new ArrayList<>();
    String sql = "SELECT YXZFJE,khx,ss,khxmc,yxzh FROM " + tablename + "_DT11 WHERE MAINID = ?";
    RecordSet rs = new RecordSet();
    rs.executeQuery(sql, mainid);
    String yxzfje = "";
    String khx = "";
    String yxzh = "";
    if (rs.next()) {
      yxzfje = Util.null2String(rs.getString("YXZFJE"));
      khx = Util.null2String(rs.getString("khx"));
      yxzh = Util.null2String(rs.getString("yxzh"));
      if (!StringUtils.isBlank(yxzfje) && !"0.00".equals(yxzfje) && !"0".equals(yxzfje)) {
        if (StringUtils.isBlank(khx) || StringUtils.isBlank(yxzh)) {
          tips.add("请填写银行卡信息");
        }
      }
    }

    PaDetail pd = new PaDetail();
    pd.setInfo("银行卡信息校验");
    pd.setCheck(CollectionUtils.isEmpty(tips));
    pd.setTips(String.join(",", tips));
    return pd;
  }

  /**
   * 7、当银行支付金额不为0时，银行卡信息必填。当银行支付金额为0，且现金支付金额不为0时，银行卡信息不必填；(差旅)
   * 适用范围：付款流程、报销流程、差旅报销
   * 控制：不允许提交
   * 提示信息：
   * （当银行支付金额不为0，银行卡信息未填写时）请填写银行卡信息
   *
   * @return
   */
  public PaDetail buildBankInfoCheckCl() throws Exception {
    List<String> tips = new ArrayList<>();
    String sql = "SELECT YXZFJE,khx,ss,yxzh FROM " + tablename + "_DT10 WHERE MAINID = ?";
    RecordSet rs = new RecordSet();
    rs.executeQuery(sql, mainid);
    String yxzfje = "";
    String khx = "";
    String yxzh = "";
    if (rs.next()) {
      yxzfje = Util.null2String(rs.getString("YXZFJE"));
      khx = Util.null2String(rs.getString("khx"));
      yxzh = Util.null2String(rs.getString("yxzh"));
      if (!StringUtils.isBlank(yxzfje) && !"0.00".equals(yxzfje) && !"0".equals(yxzfje)) {
        if (StringUtils.isBlank(khx) || StringUtils.isBlank(yxzh)) {
          tips.add("请填写银行卡信息");
        }
      }
    }

    PaDetail pd = new PaDetail();
    pd.setInfo("银行卡信息校验");
    pd.setCheck(CollectionUtils.isEmpty(tips));
    pd.setTips(String.join(",", tips));
    return pd;
  }

  /**
   * 8、收款单位银行账户字符格式，限定在数字、字母和-，字符数限制5-35
   * 适用范围：付款流程、报销流程、差旅报销
   * 控制：不允许提交
   * 提示信息：
   * （当银行账户格式错误或者长度小于5或大于35时）请核实收款方银行账号信息
   */
  private PaDetail buildBankNumCheck() throws Exception {
    List<String> tips = new ArrayList<>();
    String sql = "SELECT khx,yxzfje,yxzh FROM " + tablename + "_DT11 WHERE MAINID = ?";
    RecordSet rs = new RecordSet();
    rs.executeQuery(sql, mainid);
    String khx = "";
    String yxzfje = "";
    String yxzh = "";
    String checkBank = "^[a-zA-Z0-9]{5,35}$";
    if (rs.next()) {
      khx = Util.null2String(rs.getString("khx"));
      yxzfje = Util.null2String(rs.getString("yxzfje"));
      yxzh = Util.null2String(rs.getString("yxzh"));
    }
    //联合通用报销临时修改
    if ("lhtybx".equals(unNumberNew) || "xgtyfk".equals(unNumberNew)||"xgtybx".equals(unNumberNew)){
      if (StringUtils.isBlank(khx) || StringUtils.isBlank(yxzh)) {
        tips.add("请核实收款方银行账号信息");
      }else if (!yxzh.matches(checkBank)){//限定在数字、字母和-，字符数限制5-35
        tips.add("请核实收款方银行账号信息");
      }
    }else{
      if (StringUtils.isBlank(khx) || khx.contains(",") || LuhnUtil.checkString(khx.replaceAll(" ", "")) || StringUtils.isBlank(yxzh)) {
        tips.add("请核实收款方银行账号信息");
      }else if (!yxzh.matches(checkBank)){//限定在数字、字母和-，字符数限制5-35
        tips.add("请核实收款方银行账号信息");
      }
    }
    if (yxzfje.equals("0") || StringUtils.isBlank(yxzfje)){
      tips=tips.stream().filter(v ->!v.contains("请核实收款方银行账号信息")).collect(Collectors.toList());
    }
    PaDetail pd = new PaDetail();
    pd.setInfo("收款单位银行账户校验");
    pd.setCheck(CollectionUtils.isEmpty(tips));
    pd.setTips(String.join(",", tips));
    return pd;
  }

  /**
   * 8、收款单位银行账户字符格式，限定在数字、字母和-，字符数限制5-35(差旅)
   * 适用范围：付款流程、报销流程、差旅报销
   * 控制：不允许提交
   * 提示信息：
   * （当银行账户格式错误或者长度小于5或大于35时）请核实收款方银行账号信息
   */
  private PaDetail buildBankNumCheckCl() throws Exception {
    List<String> tips = new ArrayList<>();
    String sql = "SELECT khx,yxzfje,yxzh FROM " + tablename + "_DT10 WHERE MAINID = ?";
    RecordSet rs = new RecordSet();
    rs.executeQuery(sql, mainid);
    String khx = "";
    String yxzfje = "";
    String yxzh = "";
    String checkBank = "^[a-zA-Z0-9]{5,35}$";
    if (rs.next()) {
      khx = Util.null2String(rs.getString("khx"));
      yxzfje = Util.null2String(rs.getString("yxzfje"));
      yxzh = Util.null2String(rs.getString("yxzh"));
    }
    //联合差旅报销临时修改
    if ("clbx".equals(unNumberNew)){
        if (StringUtils.isBlank(khx) || StringUtils.isBlank(yxzh)) {
            tips.add("请核实收款方银行账号信息");
        }else if (!yxzh.matches(checkBank)){//限定在数字、字母和-，字符数限制5-35
            tips.add("请核实收款方银行账号信息");
        }
    }else{
        if (StringUtils.isBlank(khx) || LuhnUtil.checkString(khx.replaceAll(" ", "")) || StringUtils.isBlank(yxzh)) {
            tips.add("请核实收款方银行账号信息");
        }else if (!yxzh.matches(checkBank)){//限定在数字、字母和-，字符数限制5-35
            tips.add("请核实收款方银行账号信息");
        }
    }
    if (yxzfje.equals("0") || StringUtils.isBlank(yxzfje)){
      tips=tips.stream().filter(v ->!v.contains("请核实收款方银行账号信息")).collect(Collectors.toList());
    }
    PaDetail pd = new PaDetail();
    pd.setInfo("收款单位银行账户校验");
    pd.setCheck(CollectionUtils.isEmpty(tips));
    pd.setTips(String.join(",", tips));
    return pd;
  }

  /**
   * 空转0
   *
   * @param str
   * @return
   */
  private String blank2Zero(String str) {
    if ("".equals(str)) {
      return "0.00";
    } else {
      try {
        return new BigDecimal(str).toString();
      } catch (Exception e) {
        return "0.00";
      }
    }
  }

  /**
   * 9、特殊要求的附件专区未上传附件。
   * 适用范围：付款流程、报销流程、差旅报销
   * 控制：仅提示，允许发起流程
   * 提示信息：
   * （当存在未上传的附件专区时，进行提示）请根据附件要求，在专区上传相应审核附件。
   */
  public PaDetail buildAttachmentCheck() {
    List<String> tips = new ArrayList<>();
    //目前总部通用付款，分支机构通用付款,托收业务流程,分支机构通用报销,总部通用报销进行此校验，其他流程默认通过
    if ("zbtyfk".equals(unNumberNew)||"fzjgtyfk".equals(unNumberNew)||"fyft".equals(unNumberNew) ||"fzjgtybx".equals(unNumberNew)||"zbtybx".equals(unNumberNew)||"jjhtyfk".equals(unNumberNew)||"zgtyfk".equals(unNumberNew)){
      String sql = "SELECT YSKM FROM " + tablename + "_DT8 WHERE MAINID = ?";
      String sql1 = "select %s from %s where id = ?";
      RecordSet rs = new RecordSet();
      RecordSet rs1 = new RecordSet();
      rs.executeQuery(sql, mainid);
      List<String> kmList = Arrays.asList(km);
      List<String> fjfieldList = Arrays.asList(fjfield);

      boolean flag = true;
      while (rs.next()) {
        String yskm = Util.null2String(rs.getString("YSKM"));
        if (kmList.contains(yskm)) {
          String fjField = fjfieldList.get(kmList.indexOf(yskm)); //list等长
          String sqlNew = String.format(sql1, fjField, tablename);
          rs1.executeQuery(String.format(sql1, fjField, tablename), mainid);
          rs1.next();
          if ("".equals(Util.null2String(rs1.getString(fjField)))) {
            flag = false;
            break;
          }
        }
      }

      if (!flag) {
        tips.add("请根据附件要求，在专区上传相应审核附件");
      }
    }

    PaDetail pd = new PaDetail();
    pd.setInfo("科目与附件信息校验");
    pd.setCheck(CollectionUtils.isEmpty(tips));
    pd.setTips(String.join(",", tips));
    return pd;
  }

  /**
   * 10、表单必填项为空
   * 适用范围：付款流程、报销流程、差旅报销
   * 控制：不允许提交
   * 提示信息：
   * （当表单上存在必填项未填写时）”xxxxx”未填写，请核实后再提交流程
   */
  public PaDetail buildNeedValueCheck() {
    List<String> tips;
    tips = hasNeedInputField(Integer.parseInt(rid), Integer.parseInt(workflowid));
    if(!"xgtyfk".equals(unNumberNew)){
      if(tips.contains("银行账户") || tips.contains("开户行") || tips.contains("省市") || tips.contains("收款单位") || tips.contains("银行账号")){
        //支付明细表
        //先清空
        tips=tips.stream().filter(v ->!v.contains("银行账户")).collect(Collectors.toList());
        tips=tips.stream().filter(v ->!v.contains("开户行")).collect(Collectors.toList());
        tips=tips.stream().filter(v ->!v.contains("省市")).collect(Collectors.toList());
        tips=tips.stream().filter(v ->!v.contains("收款单位")).collect(Collectors.toList());
        //联合通用付款
        if("lhtyfk".equals(unNumberNew)){
          tips=tips.stream().filter(v ->!v.contains("银行账号")).collect(Collectors.toList());
        }
        //判断是本币支付还是外币支付,本币支付且银行支付金额大于0时，银行账户，开户行，省市必填；外币支付时银行账户必填。
        RecordSet sqlFindNum = new RecordSet();
        Integer num8 = 0;
        Integer num9 = 0;
        String sqlNum = "SELECT num8,num9 FROM (SELECT count(*)num8 FROM "+tablename+"_dt8 WHERE mainid = "+mainid+" ),\n" +
                "(SELECT count(*)num9 FROM "+tablename+"_dt9 WHERE mainid = "+mainid+" )";
        sqlFindNum.execute(sqlNum);
        if (sqlFindNum.next()){
          num8 = Util.getIntValue(sqlFindNum.getString("num8"));
          num9 = Util.getIntValue(sqlFindNum.getString("num9"));
        }

        String sql = "SELECT t.SKDW,t.YXZH,t.KHX,t.SS,t.yxzfje FROM "+tablename+"_DT11 t WHERE t.mainid = "+mainid+" ORDER BY t.ID ASC ";
        List<Map<String, String>> query = CommonAPI.query(sql);
        for(int i =0;i<query.size();i++){
          //银行支付金额
          String yxzfje =  query.get(i).get("yxzfje");
          //收款单位
          String skdw = query.get(i).get("skdw");
          //银行账户
          String yxzh = query.get(i).get("yxzh");
          //开户行
          String khx = query.get(i).get("khx");
          //省市
          String ss = query.get(i).get("ss");
          //行号
          Integer hh = i+1;
          if (!"0".equals(yxzfje) && StringUtils.isNotBlank(yxzfje) && num8>0){
            //本币支付时银行支付金额不为0时控制银行账户，开户行，省市必填
            if (StringUtils.isBlank(yxzh)){
              if(!"lhtyfk".equals(unNumberNew)){
                tips.add("第"+hh+"行银行账户");
              }else{
                tips.add("第"+hh+"行银行账号");
              }
            }
            if (StringUtils.isBlank(khx)){
              tips.add("第"+hh+"行开户行");
            }
            if (StringUtils.isBlank(ss)){
              tips.add("第"+hh+"行省市");
            }
          }else if(!"0".equals(yxzfje) && StringUtils.isNotBlank(yxzfje) && num9>0){
            //外币支付时银行支付金额不为0时控制银行账户必填
            if(!"lhtyfk".equals(unNumberNew)){
              tips.add("第"+hh+"行银行账户");
            }else{
              tips.add("第"+hh+"行银行账号");
            }
          }
          if (StringUtils.isBlank(skdw)){
            tips.add("第"+hh+"行收款单位");
          }
        }
      }
    }else {
      //香港通用付款处理
      tips = tips.stream().filter(v -> !v.contains("银行账户")).collect(Collectors.toList());
      tips = tips.stream().filter(v -> !v.contains("开户行")).collect(Collectors.toList());
      tips = tips.stream().filter(v -> !v.contains("收款单位")).collect(Collectors.toList());
      String sql = "SELECT t.SKDW,t.YXZH,t.KHX，t.yxzfje FROM " + tablename + "_DT11 t WHERE t.mainid = " + mainid + " ORDER BY t.ID ASC ";
      List<Map<String, String>> query = CommonAPI.query(sql);
      for (int i = 0; i < query.size(); i++) {
        String skdw = query.get(i).get("skdw");
        String yxzh = query.get(i).get("yxzh");
        String khx = query.get(i).get("khx");
        String yxzfje = query.get(i).get("yxzfje");
        Integer hh = i + 1;
        if (!"0".equals(yxzfje) && StringUtils.isNotBlank(yxzfje)&&!"0.00".equals(yxzfje)) {
          //本币支付时银行支付金额不为0时控制银行账户，开户行，省市必填
          if (StringUtils.isBlank(yxzh)) {
            tips.add("第" + hh + "行银行账户");
          }
          if (StringUtils.isBlank(khx)) {
            tips.add("第" + hh + "行开户行");
          }
        }
        if (StringUtils.isBlank(skdw)) {
          tips.add("第" + hh + "行收款单位");
        }
      }
    }
    //联合通用付款特殊处理
    if ("lhtyfk".equals(unNumberNew)) {
      if (tips.contains("费用归口部门") || tips.contains("预算项目") || tips.contains("是否投行项目") || tips.contains("税率")
              || tips.contains("部门负责人")) {
        //预算信息表
        //先清空
        tips = tips.stream().filter(v -> !v.contains("费用归口部门")).collect(Collectors.toList());
        tips = tips.stream().filter(v -> !v.contains("预算项目")).collect(Collectors.toList());
        tips = tips.stream().filter(v -> !v.contains("是否投行项目")).collect(Collectors.toList());
        tips = tips.stream().filter(v -> !v.contains("税率")).collect(Collectors.toList());
        tips = tips.stream().filter(v -> !v.contains("部门负责人")).collect(Collectors.toList());
        //判断本币,联合通用付款没有外币
        String sql = "SELECT t.fysjcdbm,t.sftxxm,t.yskmid,t.yskm,t.sl,t.gsxm FROM " + tablename + "_Dt8 t  WHERE mainid = " + mainid + " ORDER BY t.ID ASC";
        List<Map<String, String>> query = CommonAPI.query(sql);
        for (int i = 0; i < query.size(); i++) {
          //费用归口部门
          String fysjcdbm = query.get(i).get("fysjcdbm");
          //是否投行项目
          String sftxxm = query.get(i).get("sftxxm");
          //预算项目
          String yskmid = query.get(i).get("yskmid");
          //预算科目编码
          String yskm = query.get(i).get("yskm");
          //公司项目
          String gsxm = query.get(i).get("gsxm");
          //税率
          String sl = query.get(i).get("sl");
          //行号
          Integer hh = i + 1;
          if (StringUtils.isBlank(fysjcdbm)) {
            tips.add("第" + hh + "行费用归口部门");
          }
          if (StringUtils.isBlank(sftxxm)) {
            tips.add("第" + hh + "行是否投行项目");
          }
          if (StringUtils.isBlank(yskmid)) {
            tips.add("第" + hh + "行预算项目");
          }
          if (StringUtils.isBlank(sl)) {
            tips.add("第" + hh + "行税率");
          }
          //是否投行项目为是时，公司项目为必填
          if ("0".equals(sftxxm)) {
            if (StringUtils.isBlank(gsxm)) {
              tips.add("第" + hh + "行公司项目");
            }
          }
        }
        //会签部门明细表
        String sqlHq = "SELECT t.bmfzr FROM " + tablename + "_Dt10 t  WHERE mainid = " + mainid + " ORDER BY t.ID ASC";
        List<Map<String, String>> queryHq = CommonAPI.query(sqlHq);
        for (int i = 0; i < queryHq.size(); i++) {
          //部门负责人
          String bmfzr = queryHq.get(i).get("bmfzr");
          //行号
          Integer hh = i + 1;
          if (StringUtils.isBlank(bmfzr)) {
            tips.add("第" + hh + "行部门负责人");
          }
        }
      }
    } else {
      if(tips.contains("费用承担部门") || tips.contains("部门负责人") || tips.contains("预算科目") || tips.contains("预算科目编码") || tips.contains("费用承担部门负责人")
              || tips.contains("事由")){
        //预算信息表
        //先清空
        tips=tips.stream().filter(v ->!v.contains("费用承担部门")).collect(Collectors.toList());
        tips=tips.stream().filter(v ->!v.contains("部门负责人")).collect(Collectors.toList());
        tips=tips.stream().filter(v ->!v.contains("预算科目")).collect(Collectors.toList());
        tips=tips.stream().filter(v ->!v.contains("预算科目编码")).collect(Collectors.toList());
        if ("zbitfk".equals(unNumberNew)){
          tips=tips.stream().filter(v ->!v.contains("费用承担部门负责人")).collect(Collectors.toList());
        }
        if ("fzjgtyfk".equals(unNumberNew) || "jjhtyfk".equals(unNumberNew)){
          tips=tips.stream().filter(v ->!v.contains("事由")).collect(Collectors.toList());
        }
        //先判断本币
        String sql = "SELECT t.fysjcdbm,t.fycdbmfzr,t.yskmid,t.yskm,t.sy FROM "+tablename+"_Dt8 t  WHERE mainid = "+mainid+" ORDER BY t.ID ASC";
        List<Map<String, String>> query = CommonAPI.query(sql);
        for(int i =0;i<query.size();i++){
          //费用承担部门
          String fysjcdbm =  query.get(i).get("fysjcdbm");
          //部门负责人
          String fycdbmfzr = query.get(i).get("fycdbmfzr");
          //预算科目
          String yskmid = query.get(i).get("yskmid");
          //预算科目编码
          String yskm = query.get(i).get("yskm");
          //事由
          String sy = query.get(i).get("sy");
          //行号
          Integer hh = i+1;
          if ("zbitfk".equals(unNumberNew)){
            //总部it付款只有一个必填字段
            if (StringUtils.isBlank(fycdbmfzr)){
              tips.add("第"+hh+"行费用承担部门负责人");
            }
          }else if("jjhtyfk".equals(unNumberNew)){
            //基金会付款流程处理
            if (StringUtils.isBlank(yskmid)){
              tips.add("第"+hh+"行预算科目");
            }
            if (StringUtils.isBlank(sy)){
              tips.add("第"+hh+"行事由");
            }
          }else{
            if (StringUtils.isBlank(fysjcdbm)){
              tips.add("第"+hh+"行费用承担部门");
            }
            if (StringUtils.isBlank(fycdbmfzr)){
              tips.add("第"+hh+"行部门负责人");
            }
            if (StringUtils.isBlank(yskmid)){
              tips.add("第"+hh+"行预算科目");
            }
            if ("fzjgtyfk".equals(unNumberNew)){
              if (StringUtils.isBlank(sy)){
                tips.add("第"+hh+"行事由");
              }
            }
          }
        }

        //判断外币
        String sqlDt9 = "SELECT t.fysjcdbm,t.fycdbmfzr,t.yskmid,t.yskm,t.sy FROM "+tablename+"_Dt9 t  WHERE mainid = "+mainid+" ORDER BY t.ID ASC";
        List<Map<String, String>> queryDt9 = CommonAPI.query(sqlDt9);
        for(int i =0;i<queryDt9.size();i++){
          //费用承担部门
          String fysjcdbm =  queryDt9.get(i).get("fysjcdbm");
          //部门负责人
          String fycdbmfzr = queryDt9.get(i).get("fycdbmfzr");
          //预算科目
          String yskmid = queryDt9.get(i).get("yskmid");
          //事由
          String sy = queryDt9.get(i).get("sy");
          //行号
          Integer hh = i+1;
          if ("zbitfk".equals(unNumberNew)){
            //总部it付款只有一个必填字段
            if (StringUtils.isBlank(fycdbmfzr)){
              tips.add("第"+hh+"行费用承担部门负责人");
            }
          }else if("jjhtyfk".equals(unNumberNew)){
            //基金会付款流程处理
            if (StringUtils.isBlank(yskmid)){
              tips.add("第"+hh+"行预算科目");
            }
            if (StringUtils.isBlank(sy)){
              tips.add("第"+hh+"行事由");
            }
          }else{
            if (StringUtils.isBlank(fysjcdbm)){
              tips.add("第"+hh+"行费用承担部门");
            }
            if (StringUtils.isBlank(fycdbmfzr)){
              tips.add("第"+hh+"行部门负责人");
            }
            if (StringUtils.isBlank(yskmid)){
              tips.add("第"+hh+"行预算科目");
            }
            if ("fzjgtyfk".equals(unNumberNew)){
              if (StringUtils.isBlank(sy)){
                tips.add("第"+hh+"行事由");
              }
            }
          }
        }
        //会签部门明细表
        String sqlHq = "SELECT t.bmfzr FROM "+tablename+"_Dt10 t  WHERE mainid = "+mainid+" ORDER BY t.ID ASC";
        List<Map<String, String>> queryHq = CommonAPI.query(sqlHq);
        for(int i =0;i<queryHq.size();i++){
          //部门负责人
          String bmfzr =  queryHq.get(i).get("bmfzr");
          //行号
          Integer hh = i+1;
          if (StringUtils.isBlank(bmfzr)){
            tips.add("第"+hh+"行部门负责人");
          }
        }
      }
    }

    //总部工会付款特殊处理
    if ("zbghfk".equals(unNumberNew)) {
        //先清空
        tips = tips.stream().filter(v -> !v.contains("员工姓名")).collect(Collectors.toList());
        tips = tips.stream().filter(v -> !v.contains("部门")).collect(Collectors.toList());
        tips = tips.stream().filter(v -> !v.contains("银行账户")).collect(Collectors.toList());
        tips = tips.stream().filter(v -> !v.contains("开户行")).collect(Collectors.toList());
        tips = tips.stream().filter(v -> !v.contains("省市")).collect(Collectors.toList());
        tips = tips.stream().filter(v -> !v.contains("银行支付金额")).collect(Collectors.toList());

        RecordSet numrs = new RecordSet();
        String numsql = "SELECT num8,num9,num13 FROM (SELECT count(*)num8 FROM "+tablename+"_dt8 WHERE mainid = "+mainid+" ),\n" +
                "(SELECT count(*)num9 FROM "+tablename+"_dt9 WHERE mainid = "+mainid+" ),\n" +
                "(SELECT count(*)num13 FROM "+tablename+"_Dt13 WHERE mainid = "+mainid+" )";
        numrs.executeQuery(numsql);
        Integer num8 = 0;
        Integer num9 = 0;
        Integer num13 = 0;
        if (numrs.next()){
          num8 = Util.getIntValue(numrs.getString("num8"));
          num9 = Util.getIntValue(numrs.getString("num9"));
          num13 = Util.getIntValue(numrs.getString("num13"));
        }

        //先判断本币
        String dt8sql = "SELECT t.fysjcdbm FROM "+tablename+"_Dt8 t  WHERE mainid = "+mainid+" ORDER BY t.ID ASC";
        List<Map<String, String>> query = CommonAPI.query(dt8sql);
        for(int i =0;i<query.size();i++){
          //费用承担部门
          String fysjcdbm =  query.get(i).get("fysjcdbm");
          //行号
          Integer hh = i+1;
          if (StringUtils.isBlank(fysjcdbm)){
            tips.add("第"+hh+"行费用承担部门");
          }

        }
        //判断外币
        String sqlDt9 = "SELECT t.fysjcdbm FROM "+tablename+"_Dt9 t  WHERE mainid = "+mainid+" ORDER BY t.ID ASC";
        List<Map<String, String>> queryDt9 = CommonAPI.query(sqlDt9);
        for(int i =0;i<queryDt9.size();i++){
          //费用承担部门
          String fysjcdbm =  queryDt9.get(i).get("fysjcdbm");

          //行号
          Integer hh = i+1;
          if (StringUtils.isBlank(fysjcdbm)){
            tips.add("第"+hh+"行费用承担部门");
          }
        }

        String dt13sql = "SELECT t.ygxm,t.bm,t.yxzh,t.khx,t.ss,t.yxzfje FROM "+tablename+"_Dt13 t  WHERE mainid = "+mainid+" ORDER BY t.ID ASC";
        List<Map<String, String>> dt13query = CommonAPI.query(dt13sql);
        String dt11sql  =  "SELECT t.YXZH,t.KHX,t.SS,t.yxzfje FROM "+tablename+"_DT11 t WHERE t.mainid = "+mainid+" ORDER BY t.ID ASC ";
        List<Map<String, String>> dt11query = CommonAPI.query(dt11sql);
        for(int i =0;i<dt11query.size();i++) {
          //银行支付金额
          String yxzfje =  dt11query.get(i).get("yxzfje");
          //银行账户
          String yxzh = dt11query.get(i).get("yxzh");
          //开户行
          String khx = dt11query.get(i).get("khx");
          //省市
          String ss = dt11query.get(i).get("ss");
          //行号
          Integer hh = i+1;
          if (!"0".equals(yxzfje) && StringUtils.isNotBlank(yxzfje) && num8>0){
            //本币支付时银行支付金额不为0时控制银行账户，开户行，省市必填
            if (StringUtils.isBlank(yxzh)){
              tips.add("第"+hh+"行银行账户");
            }
            if (StringUtils.isBlank(khx)){
              tips.add("第"+hh+"行开户行");
            }
            if (StringUtils.isBlank(ss)){
              tips.add("第"+hh+"行省市");
            }
          }else if(!"0".equals(yxzfje) && StringUtils.isNotBlank(yxzfje) && num9>0){
            //外币支付时银行支付金额不为0时控制银行账户必填
            if (StringUtils.isBlank(yxzh)){
              tips.add("第"+hh+"行银行账户");
            }
          }

        }
        for(int i =0;i<dt13query.size();i++) {
          //员工姓名
          String ygxm = dt13query.get(i).get("ygxm");
          //部门
          String bm = dt13query.get(i).get("bm");
          //银行账户
          String yxzh = dt13query.get(i).get("yxzh");
          //开户行
          String khx = dt13query.get(i).get("khx");
          //省市
          String ss = dt13query.get(i).get("ss");
          //银行支付金额
          String yxzfje = dt13query.get(i).get("yxzfje");
          Integer hh = i+1;

          if (StringUtils.isBlank(ygxm)){
            tips.add("第"+hh+"行员工姓名");
          }
          if (StringUtils.isBlank(bm)){
            tips.add("第"+hh+"行部门");
          }
          if (StringUtils.isBlank(yxzfje)) {
            tips.add("第" + hh + "行银行支付金额");
          }


          if (!"0.00".equals(yxzfje) && !"0".equals(yxzfje) && StringUtils.isNotBlank(yxzfje) && num13>0){
            //本银行支付金额不为0时控制银行账户，开户行，省市必填
            if (StringUtils.isBlank(yxzh)){
              tips.add("第"+hh+"行银行账户");
            }
            if (StringUtils.isBlank(khx)){
              tips.add("第"+hh+"行开户行");
            }
            if (StringUtils.isBlank(ss)){
              tips.add("第"+hh+"行省市");
            }
          }
        }
     }

    //联合通用付款特殊处理
    if ("lhtyfk".equals(unNumberNew) || "zgtyfk".equals(unNumberNew)) {
      //查询主表
      tips = tips.stream().filter(v -> !v.contains("加急原因")).collect(Collectors.toList());
      RecordSet findMain = new RecordSet();
      String sql = "SELECT jjcd,jjyy,fklxx,nbsh FROM " + tablename + " WHERE id = ?";
      findMain.executeQuery(sql, mainid);
      if (findMain.next()) {
        //缓急程度
        String jjcd = Util.null2String(findMain.getString("jjcd"));
        //加急原因
        String jjyy = Util.null2String(findMain.getString("jjyy"));
        //付款类型
        String fklxx = Util.null2String(findMain.getString("fklxx"));
        //内部审核
        String nbsh = Util.null2String(findMain.getString("nbsh"));
        //加急原因处理逻辑，当紧急状态是紧急、特急的时候加急原因为必填
        if ("1".equals(jjcd) || "2".equals(jjcd)) {
          if (StringUtils.isBlank(jjyy)) {
            tips.add("加急原因");
          }
        }
        //HTO-11188 当付款类型选择“投行业务保证金”时，“内部审核”字段必填。
        if ("FKLX013".equals(fklxx)) {
          if (StringUtils.isBlank(nbsh)) {
            tips.add("内部审核");
          }
        }
      }
    } else {
      //查询主表
      tips = tips.stream().filter(v -> !v.contains("加急原因")).collect(Collectors.toList());
      RecordSet findMain = new RecordSet();
      String sql = "SELECT bmjb,szbm,bmfzrggfys,ejbmfzrggfys,ngrgh,jjcd,jjyy FROM " + tablename + " WHERE id = ?";
      findMain.executeQuery(sql, mainid);
      if (findMain.next()) {
        //部门级别
        String bmjb = Util.null2String(findMain.getString("bmjb"));
        //所属部门
        String szbm = Util.null2String(findMain.getString("szbm"));
        //一级部门领导
        String bmfzrggfys = Util.null2String(findMain.getString("bmfzrggfys"));
        //二级部门领导
        String ejbmfzrggfys = Util.null2String(findMain.getString("ejbmfzrggfys"));
        //缓急程度
        String jjcd = Util.null2String(findMain.getString("jjcd"));
        //加急原因
        String jjyy = Util.null2String(findMain.getString("jjyy"));
        //流程处理人部门负责人逻辑,只针对总部通用付款，总部IT付款
        if ("zbitfk".equals(unNumberNew) || "zbtyfk".equals(unNumberNew) || "zbghfk".equals(unNumberNew)) {
          tips = tips.stream().filter(v -> !v.contains("拟稿二级部门负责人")).collect(Collectors.toList());
          tips = tips.stream().filter(v -> !v.contains("拟稿部门负责人")).collect(Collectors.toList());
          if ("1".equals(bmjb)) {
            //一级部门时
            if ("16".equals(szbm)) {
              //所属部门为计划财务部
              tips = tips.stream().filter(v -> !v.contains("部门领导")).collect(Collectors.toList());
            } else {
              if (StringUtils.isBlank(bmfzrggfys)) {
                tips.add("部门领导");
              }
            }
          } else if ("2".equals(bmjb)) {
            //二级部门时
            //先清空
            tips = tips.stream().filter(v -> !v.contains("部门领导")).collect(Collectors.toList());
            if ("16".equals(szbm)) {
              if (StringUtils.isBlank(bmfzrggfys)) {
                tips.add("部门领导");
              }
            } else {
              if (StringUtils.isBlank(ejbmfzrggfys)) {
                tips.add("部门领导");
              }
            }

          }
        }
        //分支机构通用付款区别于总部
        if ("fzjgtyfk".equals(unNumberNew)) {
          if (StringUtils.isBlank(ejbmfzrggfys)) {
            tips.add("部门负责人");
          }
        }

        //加急原因处理逻辑，当紧急状态是紧急、特急的时候加急原因为必填
        if ("1".equals(jjcd) || "2".equals(jjcd)) {
          if (StringUtils.isBlank(jjyy)) {
            tips.add("加急原因");
          }
        }
      }
    }

    //香港通用付款特殊处理
    if("xgtyfk".equals(unNumberNew)){
      tips=tips.stream().filter(v ->!v.contains("所属机构")).collect(Collectors.toList());
      tips=tips.stream().filter(v ->!v.contains("部门负责人")).collect(Collectors.toList());
      tips=tips.stream().filter(v ->!v.contains("预算科目")).collect(Collectors.toList());
      tips=tips.stream().filter(v ->!v.contains("金额")).collect(Collectors.toList());

      String xgDt8 = "SELECT t.ssjg,t.je,t.yskm,t.fysjcdbm FROM "+tablename+"_Dt8 t  WHERE mainid = "+mainid+" ORDER BY t.ID ASC";
      List<Map<String, String>> queryDt8 = CommonAPI.query(xgDt8);
      for(int i = 0;i<queryDt8.size();i++){
        String ssjg = queryDt8.get(i).get("ssjg");
        String je = queryDt8.get(i).get("je");
        String yskm = queryDt8.get(i).get("yskm");
        String fysjcdbm = queryDt8.get(i).get("fysjcdbm");
        Integer hh = i+1;
        if (StringUtils.isBlank(ssjg)){
          tips.add("第"+hh+"行所属机构");
        }
        if (StringUtils.isBlank(je)){
          tips.add("第"+hh+"行金额");
        }
        if (StringUtils.isBlank(yskm)){
          tips.add("第"+hh+"行预算科目");
        }
        if (StringUtils.isBlank(fysjcdbm)){
          tips.add("第"+hh+"行费用承担部门");
        }
      }
    }

    //总部it付款，信息技术部拟稿时，内部审核为必填
    if ("zbitfk".equals(unNumberNew)){
      RecordSet findIt = new RecordSet();
      String sqlIt = "SELECT szbm,nbsh FROM "+tablename+" WHERE id = ?";
      findIt.executeQuery(sqlIt,mainid);
      if (findIt.next()){
           //获取所在部门
           String szbm = Util.null2String(findIt.getString("szbm"));
           //内部审核
           String nbsh = Util.null2String(findIt.getString("nbsh"));
           if ("15".equals(szbm)){
             //所在部门为信息技术部
             if (StringUtils.isBlank(nbsh)){
               tips.add("内部审核");
             }
           }
      }
    }
    //托收业务流程,一级部门负责人，二级部门负责人逻辑
    if ("fyft".equals(unNumberNew)){
      //查询主表
      RecordSet findMainFy = new RecordSet();
      String sqlFy = "SELECT bmjb,szbm,yjbmfzrxs,ejbmfzrxs,ngr FROM "+tablename+" WHERE id = ?";
      findMainFy.executeQuery(sqlFy,mainid);
      if (findMainFy.next()){
        //所属部门
        String szbm = Util.null2String(findMainFy.getString("szbm"));
        //一级部门负责人（显示）
        String yjbmfzrxs = Util.null2String(findMainFy.getString("yjbmfzrxs"));
        //二级部门负责人（显示）
        String ejbmfzrxs = Util.null2String(findMainFy.getString("ejbmfzrxs"));
        //拟稿人
        String ngr = Util.null2String(findMainFy.getString("ngr"));
        RecordSet findMainJb = new RecordSet();
        String sqlFindjb = " select a.id,a.lastname,seclevel,departmentid,departmentname,supdepid,deptDepth,deptDirectors,deptLeaders " +
                " from hrmresource a, hrmdepartment b,hrmdepartmentdefined c " +
                " where a.departmentid=b.id and b.id=c.deptid and a.id=? ";
        findMainJb.executeQuery(sqlFindjb,ngr);
        if (findMainJb.next()){
          //先清空
          tips=tips.stream().filter(v ->!v.contains("一级部门负责人（显示）")).collect(Collectors.toList());
          tips=tips.stream().filter(v ->!v.contains("二级部门负责人（显示）")).collect(Collectors.toList());
          //部门级别
          String deptDepth = Util.null2String(findMainJb.getString("deptDepth"));
          if ("16".equals(szbm)){
            //所在部门为计划财务部
          }else{
            if ("1".equals(deptDepth)){
              //一级部门时
              if (StringUtils.isBlank(yjbmfzrxs)){
                tips.add("部门领导");
              }
            }else if ("2".equals(deptDepth)){
              //二级部门时
              if (StringUtils.isBlank(ejbmfzrxs)){
                tips.add("部门领导");
              }
            }
          }
        }
      }
    }
    PaDetail pd = new PaDetail();
    pd.setInfo("表单必填校验");
    pd.setCheck(CollectionUtils.isEmpty(tips));
    tips = tips.stream().map(tip -> tip += "为必填项").collect(Collectors.toList());
    pd.setTips(String.join(",", tips));
    return pd;
  }

  /**
   * 10、表单必填项为空(报销)
   * 适用范围：付款流程、报销流程、差旅报销
   * 控制：不允许提交
   * 提示信息：
   * （当表单上存在必填项未填写时）”xxxxx”未填写，请核实后再提交流程
   */
  public PaDetail buildNeedValueCheckBx() {
    List<String> tips;
    tips = hasNeedInputField(Integer.parseInt(rid), Integer.parseInt(workflowid));
    if(!"xgtybx".equals(unNumberNew)){
      if(tips.contains("银行账号") || tips.contains("开户行") || tips.contains("省市") || tips.contains("员工姓名")){
        //支付明细表
        //先清空
        tips=tips.stream().filter(v ->!v.contains("银行账号")).collect(Collectors.toList());
        tips=tips.stream().filter(v ->!v.contains("开户行")).collect(Collectors.toList());
        tips=tips.stream().filter(v ->!v.contains("省市")).collect(Collectors.toList());
        tips=tips.stream().filter(v ->!v.contains("员工姓名")).collect(Collectors.toList());
        //判断是本币支付还是外币支付,本币支付且银行支付金额大于0时，银行账户，开户行，省市必填；外币支付时银行账户必填。
        RecordSet sqlFindNum = new RecordSet();
        Integer num8 = 0;
        Integer num9 = 0;
        String sqlNum = "SELECT num8,num9 FROM (SELECT count(*)num8 FROM "+tablename+"_dt8 WHERE mainid = "+mainid+" ),\n" +
                "(SELECT count(*)num9 FROM "+tablename+"_dt9 WHERE mainid = "+mainid+" )";
        sqlFindNum.execute(sqlNum);
        if (sqlFindNum.next()){
          num8 = Util.getIntValue(sqlFindNum.getString("num8"));
          num9 = Util.getIntValue(sqlFindNum.getString("num9"));
        }

        String sql = "SELECT t.ygxm,t.YXZH,t.KHX,t.SS,t.yxzfje FROM "+tablename+"_DT11 t WHERE t.mainid = "+mainid+" ORDER BY t.ID ASC ";
        List<Map<String, String>> query = CommonAPI.query(sql);
        for(int i =0;i<query.size();i++){
          //银行支付金额
          String yxzfje =  query.get(i).get("yxzfje");
          //员工姓名
          String ygxm = query.get(i).get("ygxm");
          //银行账号
          String yxzh = query.get(i).get("yxzh");
          //开户行
          String khx = query.get(i).get("khx");
          //省市
          String ss = query.get(i).get("ss");
          //行号
          Integer hh = i+1;
          if (!"0".equals(yxzfje) && StringUtils.isNotBlank(yxzfje) && num8>0){
            //本币支付时银行支付金额不为0时控制银行账户，开户行，省市必填
            if (StringUtils.isBlank(yxzh)){
              tips.add("第"+hh+"行银行账号");
            }
            if (StringUtils.isBlank(khx)){
              tips.add("第"+hh+"行开户行");
            }
            if (StringUtils.isBlank(ss)){
              tips.add("第"+hh+"行省市");
            }
          }else if(!"0".equals(yxzfje) && StringUtils.isNotBlank(yxzfje) && num9>0){
            //外币支付时银行支付金额不为0时控制银行账户必填
            if (StringUtils.isBlank(yxzh)){
              tips.add("第"+hh+"行银行账号");
            }
          }
          if (StringUtils.isBlank(ygxm)){
            tips.add("第"+hh+"行员工姓名");
          }

        }
      }
    }else {
      //香港通用报销特殊处理，无本币和外币区分
      tips = tips.stream().filter(v -> !v.contains("银行账户")).collect(Collectors.toList());
      tips = tips.stream().filter(v -> !v.contains("开户行")).collect(Collectors.toList());
      String sql = "SELECT t.YXZH,t.KHX，t.yxzfje FROM " + tablename + "_DT11 t WHERE t.mainid = " + mainid + " ORDER BY t.ID ASC ";
      List<Map<String, String>> query = CommonAPI.query(sql);
      for (int i = 0; i < query.size(); i++) {
        //银行支付金额
        String yxzfje = query.get(i).get("yxzfje");
        //开户行
        String khx = query.get(i).get("khx");
        //银行账号
        String yxzh = query.get(i).get("yxzh");
        Integer hh = i + 1;
        if (!"0".equals(yxzfje) && StringUtils.isNotBlank(yxzfje)&&!"0.00".equals(yxzfje)) {
          if (StringUtils.isBlank(yxzh)) {
            tips.add("第" + hh + "行银行账户");
          }
          if (StringUtils.isBlank(khx)) {
            tips.add("第" + hh + "行开户行");
          }
        }
      }
    }

    if(tips.contains("报销人") || tips.contains("费用承担部门") || tips.contains("预算科目") || tips.contains("预算科目编码") || tips.contains("报销人部门领导")
            || tips.contains("事由")|| tips.contains("部门负责人")){
      //预算信息表
      //先清空
      tips=tips.stream().filter(v ->!v.contains("报销人")).collect(Collectors.toList());
      tips=tips.stream().filter(v ->!v.contains("费用承担部门")).collect(Collectors.toList());
      tips=tips.stream().filter(v ->!v.contains("预算科目")).collect(Collectors.toList());
      tips=tips.stream().filter(v ->!v.contains("预算科目编码")).collect(Collectors.toList());
      tips=tips.stream().filter(v ->!v.contains("费用承担部门负责人")).collect(Collectors.toList());
      tips=tips.stream().filter(v ->!v.contains("事由")).collect(Collectors.toList());
      tips=tips.stream().filter(v ->!v.contains("部门负责人")).collect(Collectors.toList());
      //先判断本币
      String sql = "SELECT t.bxr,t.fysjcdbm,t.fycdbmfzr,t.yskmid,t.yskm,t.sy FROM "+tablename+"_Dt8 t  WHERE mainid = "+mainid+" ORDER BY t.ID ASC";
      List<Map<String, String>> query = CommonAPI.query(sql);
      for(int i =0;i<query.size();i++){
        //报销人
        String bxr =  query.get(i).get("bxr");
        //费用承担部门
        String fysjcdbm =  query.get(i).get("fysjcdbm");
        //报销人部门领导
        String fycdbmfzr = query.get(i).get("fycdbmfzr");
        //预算科目
        String yskmid = query.get(i).get("yskmid");
        //事由
        String sy = query.get(i).get("sy");
        //行号
        Integer hh = i+1;
        if (StringUtils.isBlank(bxr)){
          tips.add("第"+hh+"行报销人");
        }
        if (StringUtils.isBlank(fysjcdbm)){
          tips.add("第"+hh+"行费用承担部门");
        }
        if (StringUtils.isBlank(fycdbmfzr)){
          tips.add("第"+hh+"行报销人部门领导");
        }
        if (StringUtils.isBlank(yskmid)){
          tips.add("第"+hh+"行预算科目");
        }
        //联合通用报销事由必填
        if ("lhtybx".equals(unNumberNew)){
            if (StringUtils.isBlank(sy)){
                tips.add("第"+hh+"行事由");
            }
        }
      }

      //联合通用报销没有外币
      if (!"lhtybx".equals(unNumberNew)){
        //判断外币
        String sqlDt9 = "SELECT t.bxr,t.fysjcdbm,t.fycdbmfzr,t.yskmid,t.yskm,t.sy FROM "+tablename+"_Dt9 t  WHERE mainid = "+mainid+" ORDER BY t.ID ASC";
        List<Map<String, String>> queryDt9 = CommonAPI.query(sqlDt9);
        for(int i =0;i<queryDt9.size();i++){
          //报销人
          String bxr =  queryDt9.get(i).get("bxr");
          //费用承担部门
          String fysjcdbm =  queryDt9.get(i).get("fysjcdbm");
          //部门负责人
          String fycdbmfzr = queryDt9.get(i).get("fycdbmfzr");
          //预算科目
          String yskmid = queryDt9.get(i).get("yskmid");
          //事由
          String sy = queryDt9.get(i).get("sy");
          //行号
          Integer hh = i+1;
          if (StringUtils.isBlank(bxr)){
            tips.add("第"+hh+"行报销人");
          }
          if (StringUtils.isBlank(fysjcdbm)){
            tips.add("第"+hh+"行费用承担部门");
          }
          if (StringUtils.isBlank(fycdbmfzr)){
            tips.add("第"+hh+"行报销人部门领导");
          }
          if (StringUtils.isBlank(yskmid)){
            tips.add("第"+hh+"行预算科目");
          }
        }
      }

      //会签部门 部门负责人排除党委、董事会，经营管理层
      RecordSet rsbmfzr = new RecordSet();
      String szbmid = "";
      String sqlbmfzr = "select szbm from "+tablename+"  where requestid = ?";
      rsbmfzr.executeQuery(sqlbmfzr,rid);
      if(rsbmfzr.next()){
        szbmid = Util.null2String(rsbmfzr.getString("szbm"));
      }
      if("zbtybx".equals(unNumberNew)){
        if(!"695".equals(szbmid)&&!"696".equals(szbmid)&&!"2".equals(szbmid)){
          String sqlHq = "SELECT t.bmfzr FROM "+tablename+"_Dt10 t  WHERE mainid = "+mainid+" ORDER BY t.ID ASC";
          List<Map<String, String>> queryHq = CommonAPI.query(sqlHq);
          for(int i =0;i<queryHq.size();i++){
            //部门负责人
            String bmfzr =  queryHq.get(i).get("bmfzr");
            //行号
            Integer hh = i+1;
            if (StringUtils.isBlank(bmfzr)){
              tips.add("第"+hh+"行部门负责人");
            }
          }
        }
      }else {
        //会签部门明细表
        String sqlHq = "SELECT t.bmfzr FROM "+tablename+"_Dt10 t  WHERE mainid = "+mainid+" ORDER BY t.ID ASC";
        List<Map<String, String>> queryHq = CommonAPI.query(sqlHq);
        for(int i =0;i<queryHq.size();i++){
          //部门负责人
          String bmfzr =  queryHq.get(i).get("bmfzr");
          //行号
          Integer hh = i+1;
          if (StringUtils.isBlank(bmfzr)){
            tips.add("第"+hh+"行部门负责人");
          }
        }
      }
    }

    //香港通用报销特殊处理
    if("xgtybx".equals(unNumberNew)){
      //先清空
      tips=tips.stream().filter(v ->!v.contains("报销人部门领导")).collect(Collectors.toList());
      tips=tips.stream().filter(v ->!v.contains("所属机构")).collect(Collectors.toList());
      tips=tips.stream().filter(v ->!v.contains("费用承担部门")).collect(Collectors.toList());
      tips=tips.stream().filter(v ->!v.contains("费用发生日期")).collect(Collectors.toList());
      tips=tips.stream().filter(v ->!v.contains("预算科目")).collect(Collectors.toList());
      tips=tips.stream().filter(v ->!v.contains("金额")).collect(Collectors.toList());

      String dt8sql = "SELECT t.bxrbmld,t.ssjg,t.fysjcdbm,t.fyfsrq,t.yskmid,t.je  FROM "+tablename+"_Dt8 t WHERE mainid = "+mainid+" ORDER BY t.ID ASC";
      List<Map<String, String>> queryDt8 = CommonAPI.query(dt8sql);
      for(int i = 0;i<queryDt8.size();i++){
        //报销人部门领导
        String bxrbmld = queryDt8.get(i).get("bxrbmld");
        //所属机构
        String ssjg = queryDt8.get(i).get("ssjg");
        //费用承担部门
        String fysjcdbm = queryDt8.get(i).get("fysjcdbm");
        //费用发生日期
        String fyfsrq = queryDt8.get(i).get("fyfsrq");
        //预算科目
        String yskmid = queryDt8.get(i).get("yskmid");
        //金额
        String je = queryDt8.get(i).get("je");
        Integer hh = i+1;
        if (StringUtils.isBlank(bxrbmld)){
          tips.add("第"+hh+"行报销人部门领导");
        }
        if (StringUtils.isBlank(ssjg)){
          tips.add("第"+hh+"行所属机构");
        }
        if (StringUtils.isBlank(fysjcdbm)){
          tips.add("第"+hh+"行费用承担部门");
        }
        if (StringUtils.isBlank(fyfsrq)){
          tips.add("第"+hh+"行费用发生日期");
        }
        if (StringUtils.isBlank(yskmid)){
          tips.add("第"+hh+"行预算科目");
        }
        if (StringUtils.isBlank(je)){
          tips.add("第"+hh+"行金额");
        }
      }
    }
    //总部通用报销特殊处理
    if ("zbtybx".equals(unNumberNew)) {
      //先清空
      tips = tips.stream().filter(v -> !v.contains("部门领导")).collect(Collectors.toList());
      //明细表8和明细表9
      String sqlDt8 = "SELECT t.bxrbm,t.bxr,t.fycdbmfzr FROM " + tablename + "_Dt8 t WHERE mainid = "+mainid+" ORDER BY t.ID ASC";
      List<Map<String, String>> queryDt8 = CommonAPI.query(sqlDt8);
      String sqlDt9 = "SELECT t.bxrbm,t.bxr,t.fycdbmfzr FROM " + tablename + "_Dt9 t WHERE mainid = "+mainid+" ORDER BY t.ID ASC";
      List<Map<String,String>>  queryDt9 = CommonAPI.query(sqlDt9);
      queryDt8.addAll(queryDt9);

      //查询主表
      RecordSet findNgr = new RecordSet();
      String sql = "SELECT ngr , bmfzr_kf FROM "+tablename+" WHERE id = ?";
      findNgr.executeQuery(sql,mainid);
      //拟稿人
      String ngr = "";
      //部门领导
      String bmfzr_kf = "";
      if(findNgr.next()){
        ngr = Util.null2String(findNgr.getString("ngr"));
        bmfzr_kf = Util.null2String(findNgr.getString("bmfzr_kf"));
      }

      List<String> bxrs = new ArrayList<>();
      for(int i =0;i<queryDt8.size();i++){
        bxrs.add(queryDt8.get(i).get("bxr"));
        String bxrbm = Util.null2String(queryDt8.get(i).get("bxrbm"));
        String fycdbmfzr = Util.null2String(queryDt8.get(i).get("fycdbmfzr"));
        Integer hh = i+1;
        if (!"695".equals(bxrbm) && !"696".equals(bxrbm) && !"2".equals(bxrbm)) {
          if (StringUtils.isBlank(fycdbmfzr)){
            tips.add("第"+hh+"行报销人部门领导");
          }
        }
      }
      //报销人与拟稿人不一致，部门领导必填校验
      if(!bxrs.contains(ngr)){
        if (StringUtils.isBlank(bmfzr_kf)){
          tips.add("部门领导");
        }
      }
      if (tips.contains("费用发生日期")||tips.contains("报销人部门领导")){
        //预算信息表
        //先清空
        tips=tips.stream().filter(v ->!v.contains("费用发生日期")).collect(Collectors.toList());
        tips=tips.stream().filter(v ->!v.contains("报销人部门领导")).collect(Collectors.toList());
        String sql1 = "SELECT t.bxrbm ,t.fyfsrq,t.fycdbmfzr FROM "+tablename+"_Dt8 t  WHERE mainid = "+mainid+" ORDER BY t.ID ASC";
        List<Map<String, String>> query = CommonAPI.query(sql1);
        for(int i =0;i<query.size();i++){
          //报销人部门领导
          String bxrbm = query.get(i).get("bxrbm");
          //费用发生日期
          String fyfsrq =  query.get(i).get("fyfsrq");
          //报销人部门领导
          String fycdbmfzr =  query.get(i).get("fycdbmfzr");
          //行号
          Integer hh = i+1;
          if (StringUtils.isBlank(fyfsrq)){
            tips.add("第"+hh+"行费用发生日期");
          }
          if (!"695".equals(bxrbm) && !"696".equals(bxrbm) && !"2".equals(bxrbm)) {
            if (StringUtils.isBlank(fycdbmfzr)){
              tips.add("第"+hh+"行报销人部门领导");
            }
          }
        }
      }
    }


    //联合通用报销特殊处理
    if ("lhtybx".equals(unNumberNew)){
      if (tips.contains("费用发生日期")||tips.contains("是否投行项目")||tips.contains("税率")){
        //预算信息表
        //先清空
        tips=tips.stream().filter(v ->!v.contains("费用发生日期")).collect(Collectors.toList());
        tips=tips.stream().filter(v ->!v.contains("是否投行项目")).collect(Collectors.toList());
        tips=tips.stream().filter(v ->!v.contains("税率")).collect(Collectors.toList());
        String sql = "SELECT t.fyfsrq,t.sftxxm,t.sl,t.txxm FROM "+tablename+"_Dt8 t  WHERE mainid = "+mainid+" ORDER BY t.ID ASC";
        List<Map<String, String>> query = CommonAPI.query(sql);
        for(int i =0;i<query.size();i++){
          //费用发生日期
          String fyfsrq =  query.get(i).get("fyfsrq");
          //是否投行项目
          String sftxxm =  query.get(i).get("sftxxm");
          //税率
          String sl = query.get(i).get("sl");
          //投行项目
          String txxm = query.get(i).get("txxm");
          //行号
          Integer hh = i+1;
          if (StringUtils.isBlank(fyfsrq)){
            tips.add("第"+hh+"行费用发生日期");
          }
          if (StringUtils.isBlank(sftxxm)){
            tips.add("第"+hh+"行是否投行项目");
          }
          if (StringUtils.isBlank(sl)){
            tips.add("第"+hh+"行税率");
          }
          //是否投行项目不为否时，投行项目必填
          if (StringUtils.isBlank(sftxxm) || "0".equals(sftxxm)){
            if (StringUtils.isBlank(txxm)){
              tips.add("第"+hh+"行投行项目");
            }
          }
        }
      }
    }


    //查询主表
    RecordSet findMain = new RecordSet();
    String sql = "SELECT jjcd,jjyy FROM "+tablename+" WHERE id = ?";
    findMain.executeQuery(sql,mainid);
    if (findMain.next()){
      //缓急程度
      String jjcd = Util.null2String(findMain.getString("jjcd"));
      //加急原因
      String jjyy = Util.null2String(findMain.getString("jjyy"));

      //加急原因处理逻辑，当紧急状态是紧急、特急的时候加急原因为必填
      if ("1".equals(jjcd) || "2".equals(jjcd)){
        if (StringUtils.isBlank(jjyy)){
          tips.add("加急原因");
        }
      }
    }
    PaDetail pd = new PaDetail();
    pd.setInfo("表单必填校验");
    pd.setCheck(CollectionUtils.isEmpty(tips));
    tips = tips.stream().map(tip -> tip += "为必填项").collect(Collectors.toList());
    pd.setTips(String.join(",", tips));
    return pd;
  }

  /**
   * 10、表单必填项为空(差旅)
   * 适用范围：付款流程、报销流程、差旅报销
   * 控制：不允许提交
   * 提示信息：
   * （当表单上存在必填项未填写时）”xxxxx”未填写，请核实后再提交流程
   */
  public PaDetail buildNeedValueCheckCl() {
    List<String> tips;
    tips = hasNeedInputField(Integer.parseInt(rid), Integer.parseInt(workflowid));
    if ("clbx".equals(unNumberNew)){
      //联合差旅报销特殊处理
      //查询主表
      RecordSet findMain = new RecordSet();
      String sql = "SELECT sfldbx,bxry,bxfs FROM "+tablename+" WHERE id = ?";
      findMain.executeQuery(sql,mainid);
      if (findMain.next()){
        //是否领导报销
        String sfldbx = Util.null2String(findMain.getString("sfldbx"));
        //报销人员
        String bxry = Util.null2String(findMain.getString("bxry"));
        //报销方式
        String bxfs = Util.null2String(findMain.getString("bxfs"));

        //领导报销时，报销人员必填
        if ("1".equals(sfldbx)){
          if (StringUtils.isBlank(bxry)){
            tips.add("报销人员");
          }
        }

        //根据报销方式判断是个人报销还是月结对公
        if("0".equals(bxfs)){
          //个人报销
          //先清空
          tips=tips.stream().filter(v ->!v.contains("银行账号")).collect(Collectors.toList());
          tips=tips.stream().filter(v ->!v.contains("开户行")).collect(Collectors.toList());
          tips=tips.stream().filter(v ->!v.contains("省市")).collect(Collectors.toList());
//          tips=tips.stream().filter(v ->!v.contains("部门")).collect(Collectors.toList());
          tips=tips.stream().filter(v ->!v.contains("报销人")).collect(Collectors.toList());
          String sqlGr = "SELECT t.YXZH,t.KHX,t.SS,t.bm,t.bxr,t.yxzfje FROM "+tablename+"_DT10 t WHERE t.mainid = "+mainid+" ORDER BY t.ID ASC ";
          List<Map<String, String>> query = CommonAPI.query(sqlGr);
          for(int i =0;i<query.size();i++){
            //部门
            String bm =  query.get(i).get("bm");
            //银行账号
            String yxzh = query.get(i).get("yxzh");
            //开户行
            String khx = query.get(i).get("khx");
            //省市
            String ss = query.get(i).get("ss");
            //报销人
            String bxr = query.get(i).get("bxr");
            //银行支付金额
            String yxzfje = query.get(i).get("yxzfje");
            //行号
            Integer hh = i+1;
            if(!"0".equals(yxzfje) && StringUtils.isNotBlank(yxzfje)){
              if (StringUtils.isBlank(yxzh)){
                tips.add("第"+hh+"行银行账号");
              }
              if (StringUtils.isBlank(khx)){
                tips.add("第"+hh+"行开户行");
              }
              if (StringUtils.isBlank(ss)){
                tips.add("第"+hh+"行省市");
              }
            }
            if (StringUtils.isBlank(bxr)){
              tips.add("第"+hh+"行报销人");
            }
          }
        }else if ("1".equals(bxfs)){
          //月结对公
          //先清空
          tips=tips.stream().filter(v ->!v.contains("收款单位")).collect(Collectors.toList());
          tips=tips.stream().filter(v ->!v.contains("开户行")).collect(Collectors.toList());
          tips=tips.stream().filter(v ->!v.contains("收款账户")).collect(Collectors.toList());
          String sqlYj = "SELECT t.skdw,t.khx,t.skzh,t.zffs,t.zfje  FROM "+tablename+"_DT19 t WHERE t.mainid = "+mainid+" ORDER BY t.ID ASC ";
          List<Map<String, String>> query = CommonAPI.query(sqlYj);
          for(int i =0;i<query.size();i++){
            //收款单位
            String skdw =  query.get(i).get("skdw");
            //开户行
            String khx = query.get(i).get("khx");
            //收款账户
            String skzh = query.get(i).get("skzh");
            //支付方式
            String zffs = query.get(i).get("zffs");
            //支付金额
            String zfje = query.get(i).get("zfje");
            //行号
            Integer hh = i+1;
            if("0".equals(zffs)){
              //银行支付时
              if(!"0".equals(zfje) && StringUtils.isNotBlank(zfje)){
                if (StringUtils.isBlank(khx)){
                  tips.add("第"+hh+"行开户行");
                }
                if (StringUtils.isBlank(skzh)){
                  tips.add("第"+hh+"行收款账户");
                }
              }
            }

            if (StringUtils.isBlank(skdw)){
              tips.add("第"+hh+"行收款单位");
            }

          }
        }
      }
    }else{
      if(tips.contains("银行账号") || tips.contains("开户行") || tips.contains("省市")){
        //支付明细表
        //先清空
        tips=tips.stream().filter(v ->!v.contains("银行账号")).collect(Collectors.toList());
        tips=tips.stream().filter(v ->!v.contains("开户行")).collect(Collectors.toList());
        tips=tips.stream().filter(v ->!v.contains("省市")).collect(Collectors.toList());
        //差旅类流程，银行支付金额大于0时，银行账户，开户行，省市必填
        String sql = "SELECT t.YXZH,t.KHX,t.SS,t.yxzfje FROM "+tablename+"_DT10 t WHERE t.mainid = "+mainid+" ORDER BY t.ID ASC ";
        List<Map<String, String>> query = CommonAPI.query(sql);
        for(int i =0;i<query.size();i++){
          //银行支付金额
          String yxzfje =  query.get(i).get("yxzfje");
          //银行账号
          String yxzh = query.get(i).get("yxzh");
          //开户行
          String khx = query.get(i).get("khx");
          //省市
          String ss = query.get(i).get("ss");
          //行号
          Integer hh = i+1;
          if (!"0".equals(yxzfje) && StringUtils.isNotBlank(yxzfje)){
            //本币支付时银行支付金额不为0时控制银行账户，开户行，省市必填
            if (StringUtils.isBlank(yxzh)){
              tips.add("第"+hh+"行银行账号");
            }
            if (StringUtils.isBlank(khx)){
              tips.add("第"+hh+"行开户行");
            }
            if (StringUtils.isBlank(ss)){
              tips.add("第"+hh+"行省市");
            }
          }
        }
      }
    }
    if(tips.contains("是否海外")||tips.contains("部门负责人")||tips.contains("出差人部门负责人")||tips.contains("出差类型")){
      //差旅费用明细表
      //先清空
      tips=tips.stream().filter(v ->!v.contains("是否海外")).collect(Collectors.toList());
      tips=tips.stream().filter(v ->!v.contains("部门负责人")).collect(Collectors.toList());
      //总部差旅报销特殊处理
      if ("zbclbx".equals(unNumberNew)){
        tips=tips.stream().filter(v ->!v.contains("出差人部门负责人")).collect(Collectors.toList());
        tips=tips.stream().filter(v ->!v.contains("出差类型")).collect(Collectors.toList());
      }
      //
      String sql = "SELECT t.sfhw,t.ccrbmfzr,t.cclx FROM "+tablename+"_Dt12 t  WHERE mainid = "+mainid+" ORDER BY t.ID ASC";
      List<Map<String, String>> query = CommonAPI.query(sql);
      for(int i =0;i<query.size();i++){
        //是否海外
        String sfhw =  query.get(i).get("sfhw");
        //部门负责人
        String ccrbmfzr =  query.get(i).get("ccrbmfzr");
        //出差类型
        String cclx =  query.get(i).get("cclx");
        //行号
        Integer hh = i+1;
        if (StringUtils.isBlank(ccrbmfzr)){
          tips.add("第"+hh+"行部门负责人");
        }
        if (StringUtils.isBlank(sfhw)){
          tips.add("第"+hh+"行是否海外");
        }
        //总部差旅报销特殊处理
        if ("zbclbx".equals(unNumberNew)){
          if (StringUtils.isBlank(cclx)){
            tips.add("第"+hh+"行出差类型");
          }
        }
      }
      //会签部门明细表
      String sqlHq = "SELECT t.bmfzr FROM "+tablename+"_Dt2 t  WHERE mainid = "+mainid+" ORDER BY t.ID ASC";
      List<Map<String, String>> queryHq = CommonAPI.query(sqlHq);
      for(int i =0;i<queryHq.size();i++){
        //部门负责人
        String bmfzr =  queryHq.get(i).get("bmfzr");
        //行号
        Integer hh = i+1;
        if (!"zbclbx".equals(unNumberNew)){
          if (StringUtils.isBlank(bmfzr)){
            tips.add("第"+hh+"行部门负责人");
          }
        }
      }

    }
    //总部差旅报销特殊处理逻辑
    if ("zbclbx".equals(unNumberNew)){
      RecordSet sqlNode = new RecordSet();
      String currentnodetype = "";
      String sqlFindType = "SELECT CURRENTNODETYPE FROM WORKFLOW_REQUESTBASE wr WHERE REQUESTID  = "+ rid;
      sqlNode.execute(sqlFindType);
      if (sqlNode.next()){
        currentnodetype = Util.null2String(sqlNode.getString("CURRENTNODETYPE"));
      }
      //会签部门明细表
      String sqlHq = "SELECT t.bmfzr,t.hqbm FROM "+tablename+"_Dt2 t  WHERE mainid = "+mainid+" ORDER BY t.ID ASC";
      List<Map<String, String>> queryHq = CommonAPI.query(sqlHq);
      for(int i =0;i<queryHq.size();i++){
        //部门负责人
        String bmfzr =  queryHq.get(i).get("bmfzr");
        //会签部门
        String hqbm =  queryHq.get(i).get("hqbm");
        //行号
        Integer hh = i+1;
          //根据当前节点类型控制部门负责人属性
          if ("1".equals(currentnodetype)){
            if (StringUtils.isBlank(hqbm)){
              tips.add("第"+hh+"行会签部门");
            }
            if (StringUtils.isBlank(bmfzr)){
              tips.add("第"+hh+"行部门负责人");
            }
          }else{
            if (StringUtils.isBlank(hqbm)){
              tips.add("第"+hh+"行会签部门");
            }
          }
      }

      //查询主表
      RecordSet findMain = new RecordSet();
      String sql = "SELECT sfldbx,bxry FROM "+tablename+" WHERE id = ?";
      findMain.executeQuery(sql,mainid);
      if (findMain.next()){
        //是否领导报销
        String sfldbx = Util.null2String(findMain.getString("sfldbx"));
        //报销人员
        String bxry = Util.null2String(findMain.getString("bxry"));

        //领导报销时，报销人员必填
        if ("1".equals(sfldbx)){
          if (StringUtils.isBlank(bxry)){
            tips.add("报销人员");
          }
        }

      }

    }
    //联合差旅报销特殊处理
    if ("clbx".equals(unNumberNew)){
      String sql = "SELECT t.cclx,t.cclxzxx,t.txxm,t.crmkh FROM "+tablename+"_Dt12 t  WHERE mainid = "+mainid+" ORDER BY t.ID ASC";
      List<Map<String, String>> query = CommonAPI.query(sql);
      for(int i =0;i<query.size();i++){
        //出差类型
        String cclx =  query.get(i).get("cclx");
        //出差类型子选项
        String cclxzxx =  query.get(i).get("cclxzxx");
        //投行项目
        String txxm =  query.get(i).get("txxm");
        //CRM客户
        String crmkh =  query.get(i).get("crmkh");
        //行号
        Integer hh = i+1;
        if (StringUtils.isBlank(cclx)){
          tips.add("第"+hh+"行出差类型");
        }
        if (StringUtils.isBlank(cclxzxx)){
          tips.add("第"+hh+"行出差类型子选项");
        }
        if ("0".equals(cclx)){
            //出差类型为商旅出差
            if ("0".equals(cclxzxx)){
                //子类型为投行项目出差时，投行项目必填
                if (StringUtils.isBlank(txxm)){
                    tips.add("第"+hh+"行投行项目");
                }
            }else if ("1".equals(cclxzxx)){
                //子类型为客户拜访出差时，CRM项目必填
                if (StringUtils.isBlank(crmkh)){
                    tips.add("第"+hh+"行CRM客户");
                }
            }
        }
      }
    }
    if(tips.contains("费用承担部门")){
      //差旅费用分摊表
      //先清空
      tips=tips.stream().filter(v ->!v.contains("费用承担部门")).collect(Collectors.toList());
      //
      String sql = "SELECT t.fycdbm FROM "+tablename+"_Dt9 t  WHERE mainid = "+mainid+" ORDER BY t.ID ASC";
      List<Map<String, String>> queryFT = CommonAPI.query(sql);
      for(int i =0;i<queryFT.size();i++){
        //费用承担部门
        String fycdbm = queryFT.get(i).get("fycdbm");
        //行号
        Integer hh = i+1;
        if (StringUtils.isBlank(fycdbm)){
          tips.add("第"+hh+"行费用承担部门");
        }
      }
    }

    //查询主表
    RecordSet findMain = new RecordSet();
    String sql = "SELECT jjcd,jjyy FROM "+tablename+" WHERE id = ?";
    findMain.executeQuery(sql,mainid);
    if (findMain.next()){
      //缓急程度
      String jjcd = Util.null2String(findMain.getString("jjcd"));
      //加急原因
      String jjyy = Util.null2String(findMain.getString("jjyy"));

      //加急原因处理逻辑，当紧急状态是紧急、特急的时候加急原因为必填
      if ("1".equals(jjcd) || "2".equals(jjcd)){
        if (StringUtils.isBlank(jjyy)){
          tips.add("加急原因");
        }
      }

    }
    PaDetail pd = new PaDetail();
    pd.setInfo("表单必填校验");
    pd.setCheck(CollectionUtils.isEmpty(tips));
    tips = tips.stream().map(tip -> tip += "为必填项").collect(Collectors.toList());
    pd.setTips(String.join(",", tips));
    return pd;
  }


  /**
   * 11、报销人=收款人
   * 适用范围：报销流程、差旅报销
   * 控制：仅提示，允许发起流程
   * 提示信息：
   * （当报销人与收款人不一致时）当报销人与收款人不一致，请确认是否无误
   */
  public PaDetail buildHrmCheck() {
    List<String> tips = new ArrayList<>();
    String sql = "SELECT YGXM FROM " + tablename + "_DT11  WHERE MAINID =?";
    RecordSet rs = new RecordSet();
    rs.executeQuery(sql, mainid);
    List<String> ysxms = new ArrayList<>();
    while (rs.next()) {
      ysxms.add(Util.null2String(rs.getString("YGXM")));
    }
    sql = "SELECT BXR FROM " + tablename + "_DT8 WHERE MAINID =?";
    rs.executeQuery(sql, mainid);
    while (rs.next()) {
      String bxr = Util.null2String(rs.getString("BXR"));
      if (!ysxms.contains(bxr)) {
        tips.add("当前报销人和收款人不一致,请确认是否无误");
        break;
      }
    }
    if (CollectionUtils.isEmpty(ysxms)) {
      tips = new ArrayList<>();
      tips.add("请先填写报销人信息");
    }
    PaDetail pd = new PaDetail();
    pd.setInfo("报销人和收款人校验");
    pd.setCheck(CollectionUtils.isEmpty(tips));
    pd.setTips(String.join(",", tips));
    return pd;
  }

  /**
   * 11、报销人=收款人(差旅)
   * 适用范围：报销流程、差旅报销
   * 控制：仅提示，允许发起流程
   * 提示信息：
   * （当报销人与收款人不一致时）当报销人与收款人不一致，请确认是否无误
   */
  public PaDetail buildHrmCheckCl() {
    List<String> tips = new ArrayList<>();
    boolean isLdbx = getIsLdbx(tablename,rid);
    RecordSet rs = new RecordSet();
    List<String> ysxms = new ArrayList<>();
    if ("zbclbx".equals(unNumberNew)||"clbx".equals(unNumberNew)){
      String bxrysql = "";
      if(isLdbx){
        bxrysql = "SELECT bxry FROM " + tablename + "  WHERE requestid =?";
        rs.executeQuery(bxrysql, rid);
        if (rs.next()) {
          ysxms = Arrays.asList(Util.null2String(rs.getString("bxry")).split(","));
        }
        String bxrsql = "SELECT bxr FROM " + tablename + "_DT10 WHERE MAINID =?";
        rs.executeQuery(bxrsql, mainid);
        while (rs.next()) {
          String bxr = Util.null2String(rs.getString("bxr"));
          if (!ysxms.contains(bxr)) {
            tips.add("当前报销人和收款人不一致,请确认是否无误");
            break;
          }
        }
        if (CollectionUtils.isEmpty(ysxms)) {
          tips = new ArrayList<>();
          tips.add("请先填写报销人信息");
        }
      }else {
        String ccr = "";
        String bxr = "";
        String bxrsql = "SELECT bxr FROM "+tablename+"_Dt10 t  WHERE mainid = ?";
        rs.executeQuery(bxrsql, mainid);
        while ((rs.next())){
          bxr = Util.null2String(rs.getString("bxr"));
        }
        String ccrsql = "SELECT ccr FROM " + tablename + "_DT12 WHERE MAINID = "+mainid;
        List<Map<String, String>> query = CommonAPI.query(ccrsql);
        for(int i =0;i<query.size();i++){
          //出差人
          ccr = query.get(i).get("ccr");
          ysxms.add(ccr);
        }
        if (!ysxms.contains(bxr)) {
          tips.add("当前报销人和收款人不一致,请确认是否无误");
        }
        if (CollectionUtils.isEmpty(ysxms)) {
          tips = new ArrayList<>();
          tips.add("请先填写出差人信息");
        }
      }
    }else {
      String bxrysql = "SELECT bxry FROM " + tablename + "  WHERE requestid =?";
      rs.executeQuery(bxrysql, rid);
      if (rs.next()) {
        ysxms = Arrays.asList(Util.null2String(rs.getString("bxry")).split(","));
      }
      String ccrsql = "SELECT ccr FROM " + tablename + "_DT10 WHERE MAINID =?";
      rs.executeQuery(ccrsql, mainid);
      while (rs.next()) {
        String ccr = Util.null2String(rs.getString("ccr"));
        if (!ysxms.contains(ccr)) {
          tips.add("当前报销人和收款人不一致,请确认是否无误");
          break;
        }
      }
      if (CollectionUtils.isEmpty(ysxms)) {
        tips = new ArrayList<>();
        tips.add("请先填写报销人信息");
      }
    }
    PaDetail pd = new PaDetail();
    pd.setInfo("报销人和收款人校验");
    pd.setCheck(CollectionUtils.isEmpty(tips));
    pd.setTips(String.join(",", tips));
    return pd;
  }

  private boolean getIsLdbx(String tablename, String rid) {
    String sfldbx = "0";
    RecordSet rs = new RecordSet();
    String sql = "SELECT sfldbx FROM " + tablename + "  WHERE requestid = '"+rid+"'";
    rs.executeQuery(sql);
    while (rs.next()){
      sfldbx = Util.null2String(rs.getString("sfldbx"));
    }
    return "0".equals(sfldbx);
  }

  /**
   * 12、预算信息-预算科目字段根据发票上传后自动填单，未进行更改。
   * 适用范围：付款流程、报销流程、差旅报销
   * 控制：仅提示，允许发起流程
   * 提示信息：
   * （将自动填单规则计算出的预算科目存一个副本，当表单上的预算科目与副本相同时）预算科目根据发票税目自动填写，请注意核对无误后，再提交流程
   */
  public PaDetail buildAutoFillFormCheck() {
    List<String> tips = new ArrayList<>();
    RecordSet sqlCheck = new RecordSet();
    Integer countDt5 = 0;
    Integer countDt6 = 0;
    String sqlDt5 = "SELECT count(*) AS count FROM "+tablename+"_DT5 WHERE mainid = ?";
    sqlCheck.executeQuery(sqlDt5,mainid);
    if (sqlCheck.next()){
      countDt5 = Util.getIntValue(sqlCheck.getString("count"));
    }
    String sqlDt6 = "SELECT count(*) AS count FROM "+tablename+"_DT6 WHERE mainid = ?";
    sqlCheck.executeQuery(sqlDt6,mainid);
    if (sqlCheck.next()){
      countDt6 = Util.getIntValue(sqlCheck.getString("count"));
    }
    if(countDt5>0 || countDt6>0){
      String sql = "SELECT YSKM,YSKMBY FROM " + tablename + "_DT8 WHERE MAINID = ?";
      RecordSet rs = new RecordSet();
      rs.executeQuery(sql, mainid);
      while (rs.next()) {
        if (Util.null2String(rs.getString("YSKM"))
                .equals(Util.null2String(rs.getString("YSKMBY")))) {
          tips.add("预算科目根据发票税目自动填写，请注意核对无误后，再提交流程");
          break;
        }
      }
    }
    PaDetail pd = new PaDetail();
    pd.setInfo("自动填单预算科目校验");
    pd.setCheck(CollectionUtils.isEmpty(tips));
    pd.setTips(String.join(",", tips));
    return pd;
  }

  /**
   * 13、收款单位=发票开具单位=合同对手方（合同流程中信息）
   * 适用范围：付款流程
   * 控制：仅提示，允许发起流程
   * 提示信息：
   * （当支付信息中“收款单位”与发票信息中“销方名称”或关联合同中“合同对手方”不一致时) 收款单位“xxxx”与发票开具单位名称/合同对手方名称不一致，请核实信息是否无误
   */
  public PaDetail buildInvoicedEqualsContractCheck() {
    List<String> tips = new ArrayList<>();
    String sql = "SELECT skdw FROM " + tablename + "_DT11 WHERE MAINID = ?";
    RecordSet rs = new RecordSet();
    rs.executeQuery(sql, mainid);
    String skdw = "";

    if (rs.next()) {
      skdw = Util.null2String(rs.getString("skdw"));
    }
    //分支机构通用付款收款单位为多行文本框，空格替换
    if ("fzjgtyfk".equals(unNumberNew)){
     skdw = skdw.replaceAll("&nbsp;"," ");
    }
    String swdbc = toDbc(skdw);//收文单位转半角
    if (StringUtils.isNotEmpty(skdw)) {
      sql = "SELECT xfmc FROM " + tablename + "_DT5 WHERE MAINID = ?";
      rs.executeQuery(sql, mainid);
      boolean flag = true;
      boolean ifNull = true; //判断是否有发票
      while (rs.next()) {
        ifNull = false;
        String xfmc = Util.null2String(rs.getString("xfmc"));
        String fpdbc = toDbc(xfmc);//发票销方名称转半角
        if (fpdbc.equals(swdbc)) {
          flag = false;
          break;
        }
      }



      if (flag && !ifNull) { //skdw != xfmc
        tips.add("收款单位“" + skdw + "”与发票开具单位名称/合同对手方名称不一致，请核实信息是否无误");
      } else {
        flag = true; //重置状态位
        sql = "SELECT htdsf FROM " + tablename + "_DT4 WHERE MAINID = ?";
        rs.executeQuery(sql, mainid);
        String htdsf = "";
        if (rs.next()) {
          htdsf = Util.null2String(rs.getString("htdsf"));
        }
        String dsfdbc = toDbc(htdsf);//合同对手方转半角
        if (StringUtils.isNotEmpty(htdsf)) {
          List<String> htdsfList = Arrays.stream(dsfdbc.split(",")).collect(Collectors.toList());
          if (htdsfList.contains(swdbc)) {
            flag = false;
          }
        }else{
          flag = false;
        }

        if (flag) {
          tips.add("收款单位“" + skdw + "”与发票开具单位名称/合同对手方名称不一致，请核实信息是否无误");
        }else if (ifNull && StringUtils.isEmpty(htdsf)){//发票开具单位和合同对手方都为空
//          tips.add("收款单位“" + skdw + "”与发票开具单位名称/合同对手方名称不一致，请核实信息是否无误");
        }
      }
    } else {
      tips.add("收款单位为空与发票开具单位名称/合同对手方名称不一致，请核实信息是否无误");
    }

    PaDetail pd = new PaDetail();
    pd.setInfo("收款单位,发票开具单位及合同对手方校验");
    pd.setCheck(CollectionUtils.isEmpty(tips));
    pd.setTips(String.join(",", tips));
    return pd;
  }

  /**
   * 14、根据收款单位名称，校对银行账户是否与历史付款流程一致。
   * 适用范围：付款流程
   * 控制：仅提示，允许发起流程
   * 提示信息：
   * （根据收款单位名称，搜索历史付款成功信息中该单位对应使用过的银行账户信息，校对本次付款银行账户是否存在，若该收款单位未使用过此银行账户，则提醒）该银行账号与该单位历史付款信息不符，请核实收款方银行账号信息
   */
  public PaDetail buildHistoryPayCheck() {
    List<String> tips = new ArrayList<>();
    String sql = "SELECT SKDW,YXZH FROM " + tablename + "_DT11 WHERE MAINID = ?";
    RecordSet rs = new RecordSet();
    rs.executeQuery(sql, mainid);
    String skdw = "";
    String yxzh = "";
    if (rs.next()) {
      skdw = Util.null2String(rs.getString("SKDW"));
      yxzh = Util.null2String(rs.getString("YXZH"));
    }
    if (StringUtils.isEmpty(skdw) || StringUtils.isEmpty(yxzh)) {
      tips.add("该银行账号与该单位历史付款信息不符，请核实收款方银行账号信息");
    } else {
      sql = "SELECT SKDW,YXZH FROM " + tablename + "_DT11 WHERE SKDW = ? AND YXZH = ?";
      rs.executeQuery(sql, skdw, yxzh);
      if (rs.getCounts() < 2) {
        tips.add("该银行账号与该单位历史付款信息不符，请核实收款方银行账号信息");
      }
      sql = "SELECT SKDW,YXZH FROM " + tablename + "_DT11 WHERE SKDW = ? ";
      rs.executeQuery(sql, skdw);
      if (rs.getCounts() == 1){
         //如果该收款单位除了自己外并无其他历史记录，则通过
          tips=tips.stream().filter(v ->!v.contains("该银行账号与该单位历史付款信息不符，请核实收款方银行账号信息")).collect(Collectors.toList());
      }
    }

    PaDetail pd = new PaDetail();
    pd.setInfo("历史付款流程校验");
    pd.setCheck(CollectionUtils.isEmpty(tips));
    pd.setTips(String.join(",", tips));
    return pd;
  }

  /**
   * 检查必填项名称
   *
   * @param requestid
   * @param workflowid
   * @return boolean
   */
  public List<String> hasNeedInputField(int requestid, int workflowid) {
    List<String> needInputFields = new ArrayList<>();
    RecordSet rs3 = new RecordSet();
    int nodeid = -1;
    String sql = "SELECT nodeid FROM workflow_flownode WHERE workflowid=" + workflowid + "  AND nodetype='0'";
    rs3.execute(sql);
    if (rs3.next()) {
      nodeid = Util.getIntValue(rs3.getString("nodeid"));
    }

    List lstDetailFields = null;
    Map<String, String> mainTblFields = null;
    try {
      WorkflowComInfo workflowTool = new WorkflowComInfo();
      int isBill = Util.getIntValue(workflowTool.getIsBill(String.valueOf(workflowid)));
      int formID = Util.getIntValue(workflowTool.getFormId(String.valueOf(workflowid)));
      FieldInfo fieldTool = new FieldInfo();
      fieldTool.setRequestid(requestid);
      fieldTool.GetManTableField(formID, isBill, 7);
      fieldTool.GetDetailTblFields(formID, isBill, 7);

      mainTblFields = fieldTool.getMainFieldValues();
      lstDetailFields = fieldTool.getDetailFieldValues();
    } catch (Exception e) {
      logger.info("Catch a exception during instantiate the WorkflowComInfo.", e);
      return needInputFields;
    }

    sql = "select a.ismode,a.showdes from workflow_flownode a where a.workflowid=" + workflowid + " and a.nodeid=" + nodeid;
    rs3.executeSql(sql);
    if (rs3.next()) {
      int ismode = Util.getIntValue(rs3.getString("ismode"), 0);
      int showdes = Util.getIntValue(rs3.getString("showdes"), 0);
      if (ismode == 0 || ismode == 2 || (ismode == 1 && showdes == 1)) {//一般模式
        sql = "select fieldid from workflow_nodeform where ismandatory='1' and nodeid=" + nodeid;
      } else {//模板模式
        sql = "select fieldid from workflow_modeview where ismandatory='1' and nodeid=" + nodeid;
      }
      rs3.executeSql(sql);
      while (rs3.next()) {
        String fieldid = rs3.getString("fieldid");
        //是否为主表单字段
        if (mainTblFields.containsKey(fieldid)) {
          String fieldValue = mainTblFields.get(fieldid);
          if (fieldValue == null || "".equals(fieldValue)) {
            needInputFields.add(getLabelName(fieldid));
          }
        } else {
          //主表单中不存在该字段，则对多明细字段进行循环。
          for (int i = 0; i < lstDetailFields.size(); i++) {
            List tmpList = (List) lstDetailFields.get(i);
            for (int j = 0; j < tmpList.size(); j++) {
              Map<String, String> mapDetailFields = (Map<String, String>) tmpList.get(j);
              if (!mapDetailFields.containsKey(fieldid)) {
                break;
              } else {
                String fieldValue = mapDetailFields.get(fieldid);
                if (fieldValue == null || "".equals(fieldValue)) {
                  needInputFields.add(getLabelName(fieldid));
                }
              }
            }
          }
        }
      }

    }
    return needInputFields.stream().filter(StringUtil::isNotEmpty).collect(Collectors.toList());
  }

  /**
   * 获取label name
   *
   * @param fieldId 字段id
   * @return 中文名称
   */
  private String getLabelName(String fieldId) {
    String sql = "select t2.labelname from workflow_billfield t1\n" +
        "left join htmllabelinfo t2\n" +
        "on t2.indexid = t1.fieldlabel \n" +
        "where t2.labelname is not null and t1.id = ?";
    return CommonAPI.querySingleFieldWithPlaceholder(sql, "labelname", fieldId);
  }



  /**
   * 15、发票合计金额=费用明细合计金额
   * 适用范围：付款流程、报销流程、差旅报销
   * 控制：仅提示，允许发起流程
   *    * 提示信息：
   * （“票据信息-票据汇总-价税合计总额汇总金额”与“预算信息-合计金额”不同时）发票合计金额与费用明细合计金额不符，请核实后再提交流程
   */
  public PaDetail buildFpOrFyHjCheck() {
    List<String> tips = new ArrayList<>();
    RecordSet sqlFindDt7 = new RecordSet();
    String hjxxjeitxmf = "";
    String jshjzeAll = "";
    int djzs = -1;
    String sql = "SELECT hjxxjeitxmf,djzs FROM "+tablename+" WHERE requestid = ?";
    sqlFindDt7.executeQuery(sql,rid);
    if (sqlFindDt7.next()){
      DecimalFormat df = new DecimalFormat("0.00");
      hjxxjeitxmf = df.format(Double.parseDouble(Util.null2String(sqlFindDt7.getString("hjxxjeitxmf"))));
      djzs = Integer.parseInt(Util.null2String(sqlFindDt7.getString("djzs")));
    }
    if (djzs > 0) {
      sql = "SELECT JSHJZE FROM " + tablename + "_DT7 fmd WHERE MAINID = ?";
      sqlFindDt7.executeQuery(sql, mainid);
      while (sqlFindDt7.next()) {
        String jshjzeNew = Util.null2String(sqlFindDt7.getString("JSHJZE"));
        jshjzeAll = DoubleUtil.add(blank2Zero(jshjzeAll), blank2Zero(jshjzeNew), 2).toString();
      }
      if (sqlFindDt7.getCounts() > 0) {
        if (!new BigDecimal(hjxxjeitxmf).equals(new BigDecimal(jshjzeAll))) {
          tips.add("发票合计金额与费用明细合计金额不符，请核实后再提交流程");
        }
      }
    }
    PaDetail pd = new PaDetail();
    pd.setInfo("发票合计金额与费用明细合计金额校验");
    pd.setCheck(CollectionUtils.isEmpty(tips));
    pd.setTips(String.join(",", tips));
    return pd;
  }

  /**
   * 15、发票合计金额=费用明细合计金额(差旅)
   * 适用范围：付款流程、报销流程、差旅报销
   * 控制：仅提示，允许发起流程
   *    * 提示信息：
   * （“票据信息-票据汇总-价税合计总额汇总金额”与“预算信息-合计金额 - 补贴金额”不同时）发票合计金额与费用明细合计金额不符，请核实后再提交流程
   */
  public PaDetail buildFpOrFyHjCheckCl() {
    List<String> tips = new ArrayList<>();
    RecordSet sqlFindDt7 = new RecordSet();
    String hzhjjshjze = "";
    String clfy = "";
    int djzs = -1;
    String sql = "SELECT clfyhj,hzhjjshjze,djzs,mxbthj FROM "+tablename+" WHERE requestid = ?";
    sqlFindDt7.executeQuery(sql,rid);
    if (sqlFindDt7.next()){
      DecimalFormat df = new DecimalFormat("0.00");
      hzhjjshjze = df.format(Double.parseDouble(Util.null2String(sqlFindDt7.getString("hzhjjshjze"))));
      djzs = Integer.parseInt(Util.null2String(sqlFindDt7.getString("djzs")));
      //差旅费用明细-合计金额 - 差旅费用明细-补贴合计
      clfy = df.format(Double.parseDouble(Util.null2String(sqlFindDt7.getString("clfyhj"))) - Double.parseDouble(Util.null2String(sqlFindDt7.getString("mxbthj"))));
    }
    if(sqlFindDt7.getCounts()>0 && djzs > 0){
      if (!new BigDecimal(clfy).equals(new BigDecimal(hzhjjshjze))){
        tips.add("发票合计金额与费用明细合计金额不符，请核实后再提交流程");
      }
    }
    PaDetail pd = new PaDetail();
    pd.setInfo("发票合计金额与费用明细合计金额校验");
    pd.setCheck(CollectionUtils.isEmpty(tips));
    pd.setTips(String.join(",", tips));
    return pd;
  }

  /**
   * 半角转全角
   * @param input
   * @return
   */
  public String toSbc(String input){
    char[] c = input.toCharArray();
    for (int i=0;i<c.length;i++){
      if(c[i] == 32){
        c[i] = (char)12288;
        continue;
      }
      if(c[i]<127){
        c[i] = (char)(c[i]+65248);
      }
    }
    return new String(c);
  }

  /**
   * 全角转半角
   * @param input
   * @return
   */
  public String toDbc(String input){
    char[] c = input.toCharArray();
    for(int i=0;i<c.length;i++){
      if(c[i] == 12288){
        c[i] = (char) 32;
        continue;
      }
      if (c[i]>65280 && c[i] <65375){
        c[i] = (char) (c[i] - 65248);
      }
    }
    return new String(c);
  }
}
