/**
   * @param outId
   * @param productIdSet
   * @param eachRuleBean
   * @param ruleProductList
   */
  private void getExceptProduct(
      String outId,
      Set<String> productIdSet,
      BlackRuleBean eachRuleBean,
      List<BlackRuleProductBean> ruleProductList,
      List<BaseBean> baseList) {

    for (BaseBean eachBase : baseList) {
      String productId = eachBase.getProductId();

      if (!ListTools.isEmptyOrNull(ruleProductList)) {
        for (BlackRuleProductBean eachRuleProduct : ruleProductList) {
          if (productId.equals(eachRuleProduct.getProductId())) {
            if (!productIdSet.contains(productId)) {
              productIdSet.add(productId);
            }
          }
        }
      }

      if (!StringTools.isNullOrNone(eachRuleBean.getProductType())) {
        ProductBean productBean = productDAO.find(productId);

        if (null == productBean) {
          continue;
        } else {
          String pType = String.valueOf(productBean.getType());

          if (eachRuleBean.getProductType().indexOf(pType) != -1) {
            if (!productIdSet.contains(productId)) {
              productIdSet.add(productId);
            }
          }
        }
      }
    }
  }
  @SuppressWarnings("unused")
  @Deprecated
  private void processStatsBlackWhenOutPayChanged() {

    // 获取实时已付款的数据,如果数据量大,要限制每次获取的条数
    List<OutPayChangedBean> list = outPayChangedDAO.listEntityBeans();

    if (ListTools.isEmptyOrNull(list)) return;

    Set<String> idSet = new HashSet<String>();

    for (OutPayChangedBean each : list) {
      idSet.clear();

      double backValue = 0.0d;

      String outId = each.getOutId();

      OutBean outBean = outDAO.find(outId);

      if (null == outBean) {
        outPayChangedDAO.deleteEntityBean(each.getId());

        continue;
      }

      String stafferId = outBean.getStafferId();

      BlackBean blackBean = blackDAO.findByUnique(stafferId);

      if (null == blackBean) {
        outPayChangedDAO.deleteEntityBean(each.getId());

        continue;
      }

      String refId = blackBean.getId();

      BlackOutBean boBean = blackOutDAO.findByRefIdAndTypeAndOutId(refId, 0, outId);

      if (null == boBean) {
        outPayChangedDAO.deleteEntityBean(each.getId());

        continue;
      }

      idSet.add(boBean.getId());

      BlackOutBean bo1Bean = blackOutDAO.findByRefIdAndTypeAndOutId(refId, 1, outId);

      if (null != bo1Bean) {
        idSet.add(bo1Bean.getId());
      }

      _logger.info(stafferId + " " + backValue + " " + refId + "==" + idSet);

      processOutPayChangedWithoutTransaction(stafferId, blackBean, backValue, refId, idSet);

      // 用完就删掉
      outPayChangedDAO.deleteEntityBean(each.getId());
    }
  }
  /** 当有销售单付款状态发生变化,如回款,退货, 个人领样转销售等(销售库管审批后),除回款实时,其它定时统计 {@inheritDoc} */
  public void processOutPayChangedWithoutTransaction(
      String stafferId,
      BlackBean blackBean,
      double backValue,
      String refId,
      final Set<String> idSet) {
    int maxReDate;

    int oldMaxReDate = blackBean.getDays();

    for (String eachId : idSet) {
      blackOutDAO.deleteEntityBean(eachId);
    }

    // 检查超期最长时间的销售单是否全部回款,如果全部回款,则要从超期中二次取出最大超期天数的单据,并更新超期最长的单据数据
    List<BlackOutBean> blackOutList = blackOutDAO.queryByRefIdAndType(refId, 1);

    if (ListTools.isEmptyOrNull(blackOutList)) {
      // 二次取出最大超期天数
      maxReDate = blackOutDAO.queryMaxDaysByRefIdAndType(refId, 0);
    } else {
      maxReDate = blackBean.getDays();
    }

    _logger.info("maxReDate :" + maxReDate);

    if (maxReDate > 0 && maxReDate != oldMaxReDate) {
      List<BlackOutBean> blackOut0List = blackOutDAO.queryByRefIdAndType(refId, 0);

      for (BlackOutBean each : blackOut0List) {
        if (each.getDays() == maxReDate) {
          BlackOutBean outBean = new BlackOutBean();

          outBean.setRefId(refId);
          outBean.setType(1);
          outBean.setOutId(each.getOutId());
          outBean.setDays(each.getDays());

          blackOutDAO.saveEntityBean(outBean);
        }
      }
    }

    // 回款后仍超期应收金额(不计当天发生的)
    double reDateMoney = blackBean.getMoney() - backValue;

    if (maxReDate == 0) {
      reDateMoney = 0.0d;

      backValue = blackBean.getMoney();
    }

    int blackType = processBlackTypeInner(stafferId, reDateMoney, maxReDate, false);

    // 更新黑名单列表
    blackBean.setMoney(reDateMoney);
    blackBean.setDays(maxReDate);
    blackBean.setAllMoneys(blackBean.getAllMoneys() - backValue);
    _logger.info("blackBean.setDays :" + blackBean.getDays());
    int oldBlackType = blackBean.getCredit();

    if (oldBlackType == StafferConstant.BLACK_NO && blackType != StafferConstant.BLACK_NO) {
      blackBean.setEntryDate(TimeTools.now_short());
      blackBean.setRemoveDate("");
    } else if (oldBlackType != StafferConstant.BLACK_NO && blackType == StafferConstant.BLACK_NO) {
      blackBean.setRemoveDate(TimeTools.now_short());
    }

    blackBean.setCredit(blackType);

    _logger.info("processOutPayChangedWithoutTransaction blackBean update :" + blackBean);

    blackDAO.updateEntityBean(blackBean);

    // 通知
    if (oldBlackType != blackType) {
      String msg =
          "你的信用属性发生变化,原信用属性为:【"
              + DefinedCommon.getValue("stafferBlack", oldBlackType)
              + "】,新的信用属性为:【"
              + DefinedCommon.getValue("stafferBlack", blackType)
              + "】";

      notifyManager.notifyMessage(stafferId, msg);

      _logger.info(stafferId + "--" + msg);
    }
  }
  private void processStatsBlack(String statsDate, int type) {
    final String beginDate = "2011-03-01";

    // 例外规则
    List<BlackRuleBean> ruleList = getBlackRuleForBlack();

    List<String> stafferList = outDAO.queryDistinctStafferId(beginDate, statsDate, type);

    ConditionParse condition = new ConditionParse();

    triggerLog.info("**processStatsBlack with staffer size***" + stafferList.size());
    for (String each : stafferList) {
      try {
        String stafferId = each;

        setStatsBlackCondition(statsDate, stafferId, condition);

        List<OutBean> outList = outDAO.queryEntityBeansByCondition(condition);
        triggerLog.info(each + "***processStatsBlack out size:" + outList.size());

        double outValue = 0.0d;

        double allOutValue = 0.0d;

        int maxReDate = 0;

        List<BlackOutWrap> outWrapList = new ArrayList<BlackOutWrap>();

        List<BlackOutWrap> allOutWrapList = new ArrayList<BlackOutWrap>();

        List<BlackOutWrap> reDateOutWrapList = new ArrayList<BlackOutWrap>();

        boolean exceptStaffer = false;

        for (OutBean outBean : outList) {
          boolean exceptOut = false;

          double perOutValue = 0.0d;

          int reDate = 0;

          String outId = outBean.getFullId();

          List<BaseBean> baseList = baseDAO.queryEntityBeansByFK(outId);

          Set<String> productIdSet = new HashSet<String>();

          // 刨去例外逻辑,涉及到 事业部,具体单号,销售时间,人员(这些在单据头中),具体商品,品类要涉及到单据行项目
          if (!ListTools.isEmptyOrNull(ruleList)) {
            triggerLog.info("***black rule size***" + ruleList.size());
            for (BlackRuleBean eachRuleBean : ruleList) {
              triggerLog.info(outBean + "*** out vs rule ***" + eachRuleBean);
              if (TimeTools.cdate(outBean.getOutTime(), eachRuleBean.getBeginOutTime()) >= 0
                  && TimeTools.cdate(outBean.getOutTime(), eachRuleBean.getEndOutTime()) <= 0) {
                String ruleId = eachRuleBean.getId();

                String industryId = outBean.getIndustryId();

                String industryIds = eachRuleBean.getIndustryId();

                String outIds = eachRuleBean.getOutId();

                // 事业部
                if (industryIds.indexOf(industryId) != -1) {
                  exceptStaffer = true;
                }

                // 单号
                if (outIds.indexOf(outId) != -1) {
                  exceptOut = true;

                  break;
                }

                // 人员
                boolean stafferInBlackRule = stafferIdInBlackRule(stafferId, ruleId);

                if (stafferInBlackRule) {
                  exceptStaffer = true;
                }

                // 检查品类、单品, 品类 包含单品
                List<BlackRuleProductBean> ruleProductList =
                    blackRuleProductDAO.queryEntityBeansByFK(ruleId);

                if (StringTools.isNullOrNone(eachRuleBean.getProductType())
                    && ListTools.isEmptyOrNull(ruleProductList)) {
                  continue;
                } else {
                  getExceptProduct(outId, productIdSet, eachRuleBean, ruleProductList, baseList);
                }
              } else {
                continue;
              }
            }
          }

          // 整笔是例外,直接进入下一个
          if (exceptOut) {
            continue;
          }

          // ProductIdSet 中是要刨去的商品
          double excepTotal = 0.0d;
          double total = 0.0d;

          if (!productIdSet.isEmpty()) {
            for (BaseBean eachBase : baseList) {
              String productId = eachBase.getProductId();

              for (String eachItem : productIdSet) {
                if (eachItem.equals(productId)) {
                  excepTotal += eachBase.getValue();
                }
              }
            }
          }
          total = outBean.getTotal() - excepTotal;

          // 非委托代销
          double outBackValue = sumOutBackValue(outId, productIdSet);
          // 委托代销
          double balanceBackValue = 0.0d;

          if (outBean.getOutType() == OutConstant.OUTTYPE_OUT_CONSIGN) {
            List<OutBalanceBean> balanceList = outBalanceDAO.queryExcludeSettleBack(outId, 0);

            for (OutBalanceBean eachBalance : balanceList) {
              if (eachBalance.getStatus() == 99) balanceBackValue += eachBalance.getTotal();
            }
          }
          // 其它入库中关联了销售单的
          double outForceBackValue = sumOutForceBackValue(outId, productIdSet);

          // 本单应收款 = 总金额 - 退货 - 坏账 - 折扣 - 已付款
          perOutValue =
              total
                  - outBackValue
                  - balanceBackValue
                  - outForceBackValue
                  - outBean.getBadDebts()
                  - outBean.getPromValue()
                  - outBean.getHadPay();

          triggerLog.info("***perOutValue***" + perOutValue);
          try {
            reDate = TimeTools.cdate(statsDate, outBean.getRedate());
          } catch (Exception e) {
            _logger.error("Catch you!", e);
          }

          // 超期
          if (reDate > 0) {
            outValue += perOutValue;

            BlackOutWrap outWrap = new BlackOutWrap();

            outWrap.setOutId(outId);
            outWrap.setDays(reDate);
            outWrap.setMoney(perOutValue);
            outWrap.setCustomerName(outBean.getCustomerName());

            outWrapList.add(outWrap);

            if (reDate >= maxReDate) {
              if (reDate > maxReDate) reDateOutWrapList.clear();

              BlackOutWrap reDateOutWrap = new BlackOutWrap();

              reDateOutWrap.setOutId(outId);
              reDateOutWrap.setDays(reDate);
              reDateOutWrap.setMoney(perOutValue);
              reDateOutWrap.setCustomerName(outBean.getCustomerName());

              reDateOutWrapList.add(reDateOutWrap);

              maxReDate = reDate;
            }
          }

          // 所有应收款
          allOutValue += perOutValue;

          BlackOutWrap allOutWrap = new BlackOutWrap();

          allOutWrap.setOutId(outId);
          allOutWrap.setDays(reDate);
          allOutWrap.setMoney(perOutValue);
          allOutWrap.setCustomerName(outBean.getCustomerName());

          allOutWrapList.add(allOutWrap);
        }

        int blackType = processBlackTypeInner(stafferId, outValue, maxReDate, exceptStaffer);
        BlackBean blackBean = blackDAO.findByUnique(stafferId);
        StafferBean sb = stafferDAO.find(stafferId);

        if (null == blackBean) {
          String id = commonDAO.getSquenceString20();

          BlackBean bean = new BlackBean();

          bean.setId(id);
          bean.setLogDate(statsDate);
          bean.setStafferId(stafferId);

          if (null != sb) {
            bean.setIndustryId(sb.getIndustryId());
          }
          bean.setMoney(outValue);
          bean.setDays(maxReDate);
          bean.setAllMoneys(allOutValue);
          bean.setCredit(blackType);

          if (blackType != StafferConstant.BLACK_NO) {
            bean.setEntryDate(TimeTools.now_short());
          }

          blackDAO.saveEntityBean(bean);

          saveBlackOutInner(outWrapList, allOutWrapList, reDateOutWrapList, id);
        } else {
          String id = blackBean.getId();

          blackBean.setLogDate(statsDate);
          blackBean.setMoney(outValue);
          blackBean.setDays(maxReDate);
          blackBean.setAllMoneys(allOutValue);

          if (blackBean.getCredit() == StafferConstant.BLACK_NO
              && blackType != StafferConstant.BLACK_NO) {
            blackBean.setEntryDate(TimeTools.now_short());
            blackBean.setRemoveDate("");
          } else if (blackBean.getCredit() != StafferConstant.BLACK_NO
              && blackType == StafferConstant.BLACK_NO) {
            blackBean.setRemoveDate(TimeTools.now_short());
          }

          blackBean.setCredit(blackType);

          if (null != sb) {
            blackBean.setIndustryId(sb.getIndustryId());
          }

          // 先删
          blackDAO.deleteEntityBean(id);

          blackDAO.saveEntityBean(blackBean);

          blackOutDAO.deleteEntityBeansByFK(id);

          saveBlackOutInner(outWrapList, allOutWrapList, reDateOutWrapList, id);
        }
        _logger.info("***finish processStatsBlack:" + stafferId);
      } catch (Exception e) {
        _logger.error("Exception when processStatsBlack:", e);
      }
    }

    // delete logDate 不是statsDate,人员信息更新为正常
    List<BlackBean> needDelBlackList = blackDAO.queryByLogDate(statsDate);

    for (BlackBean eachd : needDelBlackList) {
      blackDAO.deleteEntityBean(eachd.getId());

      blackOutDAO.deleteEntityBeansByFK(eachd.getId());

      stafferDAO.updateBlack(eachd.getStafferId(), StafferConstant.BLACK_NO);
    }
  }