/** 认购项目 茹化肖 */
  @Override
  @Transactional(rollbackFor = Exception.class, timeout = 30)
  public HttpResultModel<Object> subproject(SubProjectReq req) {
    HttpResultModel<Object> result = new HttpResultModel<Object>();
    Member user = memberDao.selectById(req.getUserId());
    MemberOther userOther = memberOtherDao.selectByMemberId(req.getUserId());
    Project project = projectDao.selectByPrimaryKey(req.getProjectId());
    // 1.项目不在预热或进行中或已下架
    if (project == null) {
      result.setCode(-1);
      result.setMsg("该项目暂时不能购买!");
      return result;
    }
    // 2.验证用户支付密码
    if (!MD5Util.MD5(req.getPayPwd()).equals(userOther.getPaypassword())) { // 支付密码不同
      result.setCode(-1);
      result.setMsg("支付密码错误,请重试!");
      return result;
    }
    // 3项目预热中,购买人非领投人
    if (project.getProjectstatus() == ProjectStatus.Preheating.value()
        && user.getLevel() != MemberTypeEnum.LeadInvestUser.value()) {
      result.setCode(-1);
      result.setMsg("预热中的项目只有领投资格会员可以认购");
      return result;
    }
    // 4项目众筹中,普通用户
    if (project.getProjectstatus() == ProjectStatus.Financeing.value()
        && user.getLevel() == MemberTypeEnum.CommonUser.value()) {
      result.setCode(-1);
      result.setMsg("您尚未实名认证,请先进行实名认证!");
      return result;
    }
    // 5项目众筹中,实名认证用户
    if (project.getProjectstatus() == ProjectStatus.Financeing.value()
        && user.getLevel() == MemberTypeEnum.CertificationUser.value()) {
      result.setCode(-1);
      result.setMsg("您尚未进行投资人认证,请先进行投资人认证!");
      return result;
    }
    // 新手专享判断
    if (project.getIsNovice() == 1) {
      if (projectSubscriptionDao.isMyHave(project.getId(), user.getId()) > 0) {
        result.setCode(-1);
        result.setMsg("新手专享项目只能认购一次!");
        return result;
      }
    }

    if (req.getIsLead() == 1) {
      // 领投人
      if (user.getLevel() != MemberTypeEnum.LeadInvestUser.value()) {
        result.setCode(-1);
        result.setMsg("您当前不具备领投资格,请先进行领投人认证!");
        return result;
      }
      // 领投份数小于最低份额
      if (req.getQuantity() < project.getLeadminfenshu()) {
        result.setCode(-1);
        result.setMsg("您领投的份额低于该项目要求的最低领投份!");
        return result;
      }
      // 领投份数大于该项目的剩余可领投份额
      if (req.getQuantity()
          > (project.getPreheatmaxfenshu() - project.getRediduePreheatMaxFenShu())) {
        result.setCode(-1);
        result.setMsg("您领投的份额大于该项目的剩余领投份额!");
        return result;
      }
      // 领投份数大于该项目的剩余可领投份额
      if (req.getQuantity() > (project.getFenshu() - project.getRediduePreheatMaxFenShu())) {
        result.setCode(-1);
        result.setMsg("您领投的份额大于该项目的剩余份额!");
        return result;
      }
    } else {
      // 跟投.
      // 领投份数大于该项目的剩余可领投份额
      if (req.getQuantity() > (project.getFenshu() - project.getRedidueFenshu())) {
        result.setCode(-1);
        result.setMsg("您投资的份额大于该项目的剩余份额!");
        return result;
      }
    }
    // 验证金额
    if (req.getQuantity() * project.getUnitprice() > userOther.getBalanceprice()) {
      result.setCode(-1);
      result.setMsg("您认购项目所需金额大于现有余额,请先进行充值!");
      return result;
    }
    return dealSubproject(req, user, userOther, project);
  }
  /**
   * 进行认购处理
   *
   * @return
   */
  public HttpResultModel<Object> dealSubproject(
      SubProjectReq req, Member m, MemberOther mo, Project p) {
    // 1.生成购买记录
    ProjectSubscription psr = new ProjectSubscription();
    psr.setMemberid(m.getId());
    psr.setProjectid(p.getId());
    psr.setIslead(req.getIsLead() == 1);
    psr.setAmount(req.getQuantity() * p.getUnitprice());
    psr.setFenshu(req.getQuantity());
    psr.setName(m.getTruename());
    psr.setPhoneno(m.getPhoneno());
    psr.setEmail(m.getEmail());
    psr.setIdcard(m.getIdcard());
    int res1 = projectSubscriptionDao.insertSelective(psr);
    // 2.扣减账户余额
    MemberOther updateOther = new MemberOther();
    // 余额=余额-应付款
    Float yF = (p.getUnitprice() * req.getQuantity());
    Float YR = mo.getBalanceprice();
    updateOther.setBalanceprice(YR - yF);
    updateOther.setAllowwithdrawprice(mo.getAllowwithdrawprice() - yF);
    updateOther.setMemberid(m.getId());
    int res2 = memberOtherDao.updateByMemberIdSelective(updateOther);
    // 3.插入流水.
    BalanceRecord bRecord = new BalanceRecord();
    bRecord.setAmount(-yF);
    bRecord.setMemberid(m.getId());
    bRecord.setAfteramount((float) (YR - yF));
    bRecord.setTypeid(ParseHelper.ToShort(RecordType.Invest.value()));
    bRecord.setWithwardid(p.getId());
    bRecord.setRemark("认购项目");
    bRecord.setOptname(m.getTruename());
    int res3 = blanceRecordDao.insertSelective(bRecord);
    // 4.更新项目信息
    Project updateProject = new Project();
    updateProject.setId(p.getId());
    updateProject.setRedidueFenshu(p.getRedidueFenshu() + req.getQuantity());
    updateProject.setInvestmentnumber(p.getInvestmentnumber() + 1);
    // 已购买份数除以份数*100
    int rp = updateProject.getRedidueFenshu() * 100 / p.getFenshu();
    updateProject.setSchedule(rp);
    if (req.getIsLead() == 1) // 领投
    {
      // 已购买的份数加上新的份数
      updateProject.setRediduePreheatMaxFenShu(p.getRediduePreheatMaxFenShu() + req.getQuantity());
    }
    int res4 = projectDao.updateByPrimaryKeySelective(updateProject);
    if (res1 != 1 || res2 != 1 || res3 != 1 || res4 != 1) // 每个操作都应该只有一条影响
    {
      throw new TransactionalRuntimeException("认购失败!");
    }
    int year = ParseHelper.GetInDate(new java.util.Date(), 1);
    int month = ParseHelper.GetInDate(new java.util.Date(), 2);
    int day = ParseHelper.GetInDate(new java.util.Date(), 3);

    // 您于*年*月*日认购易淘众筹项目“*”,已确认成功,确认金额*元。如有任何疑问,请致电联系客服4000-999-177
    String content =
        "您于"
            + year
            + "年"
            + month
            + "月"
            + day
            + "日"
            + "认购易淘众筹项目“"
            + p.getProjectname()
            + "”,"
            + "已确认成功,确认金额"
            + yF
            + "元。"
            + "如有任何疑问,请致电联系客服4000-999-177";

    // 发送认购短信
    SmsUtils.sendSMS(m.getPhoneno(), content);
    HttpResultModel<Object> rModel = new HttpResultModel<Object>();
    rModel.setCode(1);
    rModel.setMsg("认购成功!");
    rModel.setUrl(
        PropertyUtils.getProperty("java.wap.url") + "/home/detail?projectid=" + p.getId());
    return rModel;
  }