com.icebreak.p2p.trade.impl.InvestServiceImpl.java Source code

Java tutorial

Introduction

Here is the source code for com.icebreak.p2p.trade.impl.InvestServiceImpl.java

Source

package com.icebreak.p2p.trade.impl;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.icebreak.p2p.base.BaseBizService;
import com.icebreak.p2p.base.OpenApiBaseContextServiceBase;
import com.icebreak.p2p.dal.daointerface.RepayPlanDAO;
import com.icebreak.p2p.dal.dataobject.RepayPlanDO;
import com.icebreak.p2p.daointerface.DivisonRuleRoleDao;
import com.icebreak.p2p.daointerface.TradeDao;
import com.icebreak.p2p.daointerface.TradeDetailDao;
import com.icebreak.p2p.daointerface.UserGoldExperienceDao;
import com.icebreak.p2p.dataobject.DivisionTemplateLoanDO;
import com.icebreak.p2p.dataobject.DivsionRuleRole;
import com.icebreak.p2p.dataobject.InvestDetailDO;
import com.icebreak.p2p.dataobject.LoanDemandDO;
import com.icebreak.p2p.dataobject.ProfitAsignInfo;
import com.icebreak.p2p.dataobject.Trade;
import com.icebreak.p2p.dataobject.TradeDetail;
import com.icebreak.p2p.dataobject.TradeFlowCode;
import com.icebreak.p2p.dataobject.TradeQueryDetail;
import com.icebreak.p2p.dataobject.UserBaseInfoDO;
import com.icebreak.p2p.dataobject.UserGoldExperienceDO;
import com.icebreak.p2p.dataobject.UserRelationDO;
import com.icebreak.p2p.division.DivisionService;
import com.icebreak.p2p.division.DivisionTemplateYrdService;
import com.icebreak.p2p.integration.openapi.result.InvestReturnRequest;
import com.icebreak.p2p.loandemand.LoanDemandManager;
import com.icebreak.p2p.page.Page;
import com.icebreak.p2p.trade.InvestService;
import com.icebreak.p2p.user.UserBaseInfoManager;
import com.icebreak.p2p.user.UserRelationManager;
import com.icebreak.p2p.util.AppConstantsUtil;
import com.icebreak.p2p.util.BusinessNumberUtil;
import com.icebreak.p2p.util.CommonUtil;
import com.icebreak.p2p.util.DateUtil;
import com.icebreak.p2p.util.MoneyUtil;
import com.icebreak.p2p.util.YrdConstants;
import com.icebreak.p2p.ws.enums.DivisionPhaseEnum;
import com.icebreak.p2p.ws.enums.DivisionWayEnum;
import com.icebreak.p2p.ws.enums.LoanLimitUnitEnum;
import com.icebreak.p2p.ws.enums.RepayPlanStatusEnum;
import com.icebreak.p2p.ws.enums.SysUserRoleEnum;
import com.icebreak.p2p.ws.enums.TradeDetailStatusEnum;
import com.icebreak.p2p.ws.enums.TradeFullConditionEnum;
import com.icebreak.p2p.ws.enums.UserTypeEnum;
import com.icebreak.util.lang.util.ListUtil;
import com.icebreak.util.lang.util.StringUtil;
import com.icebreak.util.lang.util.money.Money;
import com.yiji.openapi.sdk.message.common.YzzUserAccountQueryRequest;
import com.yiji.openapi.sdk.message.common.YzzUserAccountQueryResponse;
import com.yiji.openapi.sdk.message.yzz.InvestApplyNotify;

@Service
public class InvestServiceImpl extends BaseBizService implements InvestService {

    @Autowired
    protected DivisionService divisionService;
    @Autowired
    DivisionTemplateYrdService divisionTemplateLoanService;

    @Autowired
    private RepayPlanDAO repayPlanDAO;
    @Autowired
    UserGoldExperienceDao userGoldExperienceDao;
    @Autowired
    private TradeDao tradeDao;
    @Autowired
    private TradeDetailDao tradeDetailDao;
    @Autowired
    private LoanDemandManager loanDemandManager;
    @Autowired
    private UserRelationManager userRelationManager;
    @Autowired
    private UserBaseInfoManager userBaseInfoManager;
    @Autowired
    private DivisonRuleRoleDao divisonRuleRoleDao;
    private String jjrRoleId = SysUserRoleEnum.BROKER.code();
    private String yxjgRoleId = SysUserRoleEnum.MARKETING.code();
    private String investRoleId = SysUserRoleEnum.INVESTOR.code();

    public double getDaysRuleRate(double rule, String timeLimitUnit, int timeLimit, Date effectiveDate,
            Date endDate) {
        Trade trade = new Trade();
        trade.setTimeLimitUnit(timeLimitUnit);
        trade.setTimeLimit(timeLimit);
        trade.setEffectiveDateTime(effectiveDate);
        return getDaysRuleRate(rule, trade, endDate);
    }

    private static double getDaysRuleRate(double rule, Trade trade, Date endDate) {
        String timeLimitUnit = trade.getTimeLimitUnit();
        double timeLimit = trade.getTimeLimit();
        double days = 0;
        if (LoanLimitUnitEnum.LOAN_BY_DAY.code().equals(timeLimitUnit)) {
            days = timeLimit;
        } else if (LoanLimitUnitEnum.LOAN_BY_YEAR.code().equals(timeLimitUnit)) {
            days = timeLimit * YrdConstants.TimeRelativeConstants.DAYSOFAYEAR;
        } else {
            days = Math.round(timeLimit * YrdConstants.TimeRelativeConstants.DAYSOFAYEAR / 12);
        }
        //?? ??
        if (null != trade.getEffectiveDateTime()) {
            try {
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                Calendar endTime = Calendar.getInstance();
                if (null == endDate) {
                    endTime.setTime(sdf.parse(sdf.format(Calendar.getInstance().getTime())));
                } else {
                    endTime.setTime(sdf.parse(sdf.format(endDate)));
                }
                Calendar beginTime = Calendar.getInstance();
                beginTime.setTime(sdf.parse(sdf.format(trade.getEffectiveDateTime())));
                int cutDays = (int) ((endTime.getTimeInMillis() - beginTime.getTimeInMillis()) / 1000 / 60 / 60
                        / 24);
                days = days - cutDays;
                days = (days < 0 ? 0 : days);
            } catch (Exception e) {
                Logger logger = LoggerFactory.getLogger("get DiffDate");
                logger.error("conculate diffDate throw a exceptioin!");
                logger.error(e.getMessage());
            }
        }
        BigDecimal bg = new BigDecimal(rule / YrdConstants.TimeRelativeConstants.DAYSOFAYEAR * days);
        double daysRate = bg.setScale(10, BigDecimal.ROUND_HALF_UP).doubleValue();
        return daysRate;
    }

    //
    private static double getDaysRuleRate(double rule, Trade trade) {
        return getDaysRuleRate(rule, trade, null);
    }

    public String getJjrRoleId() {
        return jjrRoleId;
    }

    public void setJjrRoleId(String jjrRoleId) {
        this.jjrRoleId = jjrRoleId;
    }

    public String getYxjgRoleId() {
        return yxjgRoleId;
    }

    public void setYxjgRoleId(String yxjgRoleId) {
        this.yxjgRoleId = yxjgRoleId;
    }

    public String getInvestRoleId() {
        return investRoleId;
    }

    public void setInvestRoleId(String investRoleId) {
        this.investRoleId = investRoleId;
    }

    @Override
    public List<DivsionRuleRole> getRuleRole(String name) {
        return this.divisonRuleRoleDao.getLstRulRole(name);
    }

    /**
     *  ??
     * @throws Exception
     */
    @Transactional(rollbackFor = Exception.class, value = "transactionManager")
    @Override
    public void investProcessor(TradeDetail detail) throws Exception {

        //?
        TradeDetail detailSaved = saveInvestOriginalTradeDetail(detail);
        //??
        addDetailDivision(detailSaved);

        tradeDao.modifyStatus(detailSaved.getTradeId(), YrdConstants.TradeStatus.TRADING);//???
        //??
        addTradeFlowCode(detailSaved);

        //??
        notifyLoanerIfFull(detailSaved);

    }

    public void createRelativeTrades(Trade trade) throws Exception {

        //?
        Date currentDate = new Date();
        //?
        Calendar cal = Calendar.getInstance();
        cal.setTime(currentDate);
        cal.add(Calendar.DATE, trade.getTimeLimit());
        trade.setEffectiveDateTime(currentDate);
        trade.setExpireDateTime(cal.getTime());
        //      trade = tradeDao.getByTradeIdWithRowLock(trade.getId());
        // ?
        tradeDao.modifyStatus(trade.getId(), YrdConstants.TradeStatus.REPAYING, currentDate, cal.getTime());
        // ???
        tradeDao.updateIsNotifiedLoaner(trade.getId(), YrdConstants.MessageNotifyConstants.ISNOTIFIED_NO);
    }

    protected void setToUserDetail(UserBaseInfoDO toUser) {
        toUser.setRealName("??001?");
        toUser.setMail(AppConstantsUtil.getCustomerServiceEmail());
        toUser.setMobile(AppConstantsUtil.getCustomerServiceMobile());
    }

    @Transactional(rollbackFor = Exception.class, value = "transactionManager")
    @Override
    public void investNotify(InvestApplyNotify notify) throws Exception {
        Map<String, Object> conditions = new HashMap<String, Object>();
        conditions.put("orderNo", notify.getOrderNo());
        List<TradeQueryDetail> list = tradeDetailDao.getTradeDetailByConditions(conditions);
        TradeQueryDetail detail = null;
        if (ListUtil.isNotEmpty(list)) {
            detail = list.get(0);
            logger.info("??" + detail.getId());
            if (!(StringUtil.equalsIgnoreCase(TradeDetailStatusEnum.IT.getCode(), detail.getTradeDetailStatus())
                    || StringUtil.equalsIgnoreCase(TradeDetailStatusEnum.AS.getCode(),
                            detail.getTradeDetailStatus()))) {
                logger.info("?" + detail.getTradeDetailStatus() + ",?");
                return;
            }
            TradeDetailStatusEnum status = null;
            if (StringUtil.equalsIgnoreCase("SUCCESS", notify.getExecuteStatus())) {
                status = TradeDetailStatusEnum.PS;
            } else if (StringUtil.equalsIgnoreCase("FAIL", notify.getExecuteStatus())) {
                status = TradeDetailStatusEnum.PF;
                tradeDetailDao.updatetStatus(detail.getId(), status.getCode());
                return;
            }

            int userVirtualMoneyId = -1;
            try {
                userVirtualMoneyId = Integer.parseInt(detail.getNote());
            } catch (NumberFormatException e) {

            }
            if (userVirtualMoneyId > 0) {
                UserGoldExperienceDO virtualMoney = userGoldExperienceDao.getById(userVirtualMoneyId);
                if (virtualMoney != null) {
                    logger.info("?0");
                    virtualMoney.setStatus("0");
                    virtualMoney.setTradeDetailId(detail.getId());
                    virtualMoney.setTradeId(detail.getTradeId());
                    userGoldExperienceDao.update(virtualMoney);
                }
            }

            tradeDao.addLoanedAmount(detail.getTradeId(), detail.getAmount());
            // ?
            //         TradeDetail detailSaved = saveInvestOriginalTradeDetail(detail);
            tradeDetailDao.updatetStatus(detail.getId(), status.getCode());
            // ??
            addDetailDivision(detail);

            tradeDao.modifyStatus(detail.getTradeId(), YrdConstants.TradeStatus.TRADING);// ???
            // ??
            //         addTradeFlowCode(detail);

            // ??
            notifyLoanerIfFull(detail);
        }
    }

    private void tradeFinish(Trade trade) throws Exception {
        logger.info("???[tradeId={}],", trade);
        Map<String, Object> map = new HashMap<String, Object>();
        //      Trade trade = tradeService.getByTradeId(tradeId);
        logger.info("tradeId" + trade.getId() + "?...");
        divisionService.transfer(trade, 0L);

        LoanDemandDO loan = loanDemandManager.queryLoanDemandByDemandId(trade.getDemandId());
        //
        addRepayPlan(trade, loan);

    }

    private void addRepayPlan(Trade trade, LoanDemandDO loanDemand) throws Exception {
        List<RepayPlanDO> planList = repayPlanDAO.findByTradeId(trade.getId());
        if (planList.size() > 0) {
            repayPlanDAO.deleteByTradeId(trade.getId()); // ????
        }

        Date nowDate = new Date();
        // ??
        LoanDemandDO loan = loanDemandManager.queryLoanDemandByDemandId(trade.getDemandId());
        long divisionTemplateLoanBaseId = loan.getDivisionTemplateId();
        DivisionTemplateLoanDO divisionTemplateLoan = divisionTemplateLoanService
                .getByBaseId(divisionTemplateLoanBaseId);
        List<DivsionRuleRole> repayRolelist = getRuleRole(
                String.valueOf(divisionTemplateLoan.getRepayTemplateId()));

        Map<String, Object> conditions2 = new HashMap<String, Object>();
        conditions2.put("roleId", SysUserRoleEnum.INVESTOR.getValue());
        conditions2.put("tradeId", trade.getId());
        conditions2.put("transferPhase", DivisionPhaseEnum.ORIGINAL_PHASE.code());
        List<TradeQueryDetail> originalDetails = loanDemandManager.getTradeDetailByConditions(conditions2);

        // 
        if (originalDetails != null && originalDetails.size() > 0) {
            for (TradeDetail detail : originalDetails) {
                int repayPeriodNo = detail.getRepayPeriodNo();
                updateInvestDetailRepayDate(detail.getId(), trade.getExpireDateTime());
            }
        }

        Map<String, Object> conditions = new HashMap<String, Object>();
        conditions.put("roleId", SysUserRoleEnum.INVESTOR.getValue());
        conditions.put("tradeId", trade.getId());
        conditions.put("transferPhase", DivisionPhaseEnum.REPAY_PHASE.code());
        List<TradeQueryDetail> details = loanDemandManager.getTradeDetailByConditions(conditions);

        if (DivisionWayEnum.MONTH_WAY.getCode().equals(loanDemand.getRepayDivisionWay())) {

            // ????
            if (details != null && details.size() > 0) {
                for (TradeDetail detail : details) {
                    int repayPeriodNo = detail.getRepayPeriodNo();
                    if (repayPeriodNo > 0) {
                        updateInvestDetailRepayDate(detail.getId(),
                                DateUtil.getDateByMonth(nowDate, repayPeriodNo));
                    }
                }
            }

            double repayCutAmount = 0; // ???
            double repayOtherAmount = 0; // ??
            if (ListUtil.isNotEmpty(repayRolelist)) {
                for (DivsionRuleRole druleRole : repayRolelist) {
                    if (druleRole.getRoleId() == SysUserRoleEnum.INVESTOR.getValue()) { // ??
                        double temp = getDaysRuleRate(druleRole.getRule(), trade) * trade.getLoanedAmount();
                        repayCutAmount = repayCutAmount + temp;
                    } else {
                        double temp = getDaysRuleRate(druleRole.getRule(), trade) * trade.getLoanedAmount();
                        repayOtherAmount = repayOtherAmount + temp;
                    }
                }
            }
            int month = trade.getMonthCount();

            double repayAmountPerMonth = new BigDecimal(repayCutAmount / month).doubleValue();// ???

            repayAmountPerMonth = Math.floor(repayAmountPerMonth);

            double repayAll = repayAmountPerMonth + repayOtherAmount + trade.getLoanedAmount(); // ??

            if (repayCutAmount > 0) {
                for (int i = 0; i < month; i++) {
                    boolean isLast = false;
                    if (i == month - 1) {
                        isLast = true;
                    }
                    storeRepayPlanDomain(trade, loanDemand, nowDate, repayAll, repayCutAmount, month, i + 1,
                            isLast);
                }
            } else {
                boolean isLast = true;
                storeRepayPlanDomain(trade, loanDemand, nowDate, repayAll, repayCutAmount, month, 1, isLast);
            }

        } else {

            // ????
            if (details != null && details.size() > 0) {
                for (TradeDetail detail : details) {
                    updateInvestDetailRepayDate(detail.getId(),
                            DateUtil.getDateByMonth(nowDate, trade.getMonthCount()));
                }
            }

            double repayCutAmount = 0; // ?
            /* ? ??tradeDetail??
             * if (ListUtil.isNotEmpty(repayRolelist)) {
               for (DivsionRuleRole druleRole : repayRolelist) {
                  double temp = getDaysRuleRate(druleRole.getRule(), trade)
                 * trade.getLoanedAmount();
                  repayCutAmount = repayCutAmount + temp;
               }
            }*/
            Map<String, Object> params = new HashMap<String, Object>();
            params.put("tradeId", trade.getId());
            List<TradeDetail> detailList = tradeDetailDao.getTradeDivisionDetailByConditions(params);
            if (null != detailList) {
                for (TradeDetail detail : detailList) {
                    repayCutAmount = repayCutAmount + detail.getAmount();
                }
            }
            double repayAmount = trade.getLoanedAmount() + repayCutAmount;
            boolean isLast = true;
            storeRepayPlanDomain(trade, loanDemand, nowDate, repayAmount, 0, 1, 1, isLast);
        }
    }

    private void storeRepayPlanDomain(Trade trade, LoanDemandDO loanDemand, Date nowDate, double repayAll,
            double investAmount, int month, int row, boolean isLast) {

        RepayPlanDO repayPlanDO = createRepayPlan(trade, loanDemand, nowDate, repayAll, investAmount, month, row,
                isLast);
        repayPlanDAO.insert(repayPlanDO);

    }

    private RepayPlanDO createRepayPlan(Trade trade, LoanDemandDO loanDemand, Date nowDate, double repayAll,
            double investAmount, int month, int row, boolean isLast) {

        RepayPlanDO repayPlanDO = new RepayPlanDO();
        repayPlanDO.setNote(String.valueOf(month));
        repayPlanDO.setPeriodNo(row);
        if (isLast) {
            repayPlanDO.setAmount(new Money(repayAll / 100));
            repayPlanDO.setOriginalAmount(new Money(trade.getLoanedAmount() / 100));
        } else {
            double repayAmountPerMonth = new BigDecimal(investAmount / month).doubleValue();
            repayAmountPerMonth = Math.floor(repayAmountPerMonth);
            repayPlanDO.setAmount(new Money(repayAmountPerMonth / 100));

        }
        repayPlanDO.setOriginalAmount(new Money(trade.getLoanedAmount() / 100));
        repayPlanDO.setStatus(RepayPlanStatusEnum.NOTPAY.code());
        repayPlanDO.setRawAddTime(nowDate);
        repayPlanDO.setRawUpdateTime(nowDate);
        Date repayDate = null;
        if (DivisionWayEnum.SIT_WAY.code().equals(loanDemand.getRepayDivisionWay())) {
            repayDate = trade.getExpireDateTime();
        } else {
            repayDate = DateUtil.getDateByMonth(nowDate, row);
        }

        repayPlanDO.setRepayDate(repayDate);
        repayPlanDO.setRepayDivisionWay(loanDemand.getRepayDivisionWay());
        repayPlanDO.setRepayUserId(loanDemand.getLoanerId());
        repayPlanDO.setRepayUserName(loanDemand.getUserName());
        repayPlanDO.setRepayUserRealName(loanDemand.getUserName());
        repayPlanDO.setTradeId(trade.getId());
        repayPlanDO.setTradeName(trade.getName());
        repayPlanDO.setPeriodCount(month);
        return repayPlanDO;
    }

    @Transactional(rollbackFor = Exception.class, value = "transactionManager")
    @Override
    public void investReturn(InvestReturnRequest request) {
        Map<String, Object> conditions = new HashMap<String, Object>();
        conditions.put("orderNo", request.getOrderNo());
        List<TradeQueryDetail> list = tradeDetailDao.getTradeDetailByConditions(conditions);
        TradeQueryDetail detail = null;
        if (ListUtil.isNotEmpty(list)) {
            detail = list.get(0);
            if (StringUtil.isNotBlank(detail.getTradeDetailStatus())
                    && detail.getTradeDetailStatus().startsWith("P")) {
                return;
            }
            TradeDetailStatusEnum status = null;
            if (StringUtil.equalsIgnoreCase("trade_success", request.getTradeStatus())) {
                status = TradeDetailStatusEnum.AS;
            } else {
                status = TradeDetailStatusEnum.AF;
            }
            tradeDetailDao.updatetStatus(detail.getId(), status.getCode());
        }

    }

    /**
     * ?
     * @param detail
     * @return
     * @throws Exception
     */
    public TradeDetail saveInvestOriginalTradeDetail(TradeDetail detail) throws Exception {
        if (detail.getRoleId() != 12
                || !DivisionPhaseEnum.ORIGINAL_PHASE.code().equals(detail.getTransferPhase())) {
            throw new Exception("?");
        }
        long tradeId = detail.getTradeId();
        Trade trade = tradeDao.getByTradeIdWithRowLock(tradeId);
        Map<String, Object> result = doCheckTrade(trade);
        result = doCheckAmount(trade, detail.getAccountId(), detail.getAmount());
        if (!((Boolean) result.get("status"))) {
            throw new RuntimeException("??:ID--" + detail.getUserId()
                    + ",?" + detail.getAmount() + "" + result.get("message"));
        }
        //      tradeDao.addLoanedAmount(tradeId, detail.getAmount());
        long detailId = tradeDetailDao.addTradeDetail(detail);
        detail.setId(detailId); //
        return detail;
    }

    /**
     * ??
     * @param detail
     * @throws Exception
     */
    protected void addDetailDivision(TradeDetail detail) throws Exception {
        Trade trade = tradeDao.getByTradeIdWithRowLock(detail.getTradeId());
        //??
        LoanDemandDO loan = loanDemandManager.queryLoanDemandByDemandId(trade.getDemandId());
        long divisionTemplateLoanBaseId = loan.getDivisionTemplateId();
        DivisionTemplateLoanDO divisionTemplateLoan = divisionTemplateLoanService
                .getByBaseId(divisionTemplateLoanBaseId);
        List<DivsionRuleRole> investRolelist = getRuleRole(
                String.valueOf(divisionTemplateLoan.getInvestTemplateId()));
        List<DivsionRuleRole> repayRolelist = getRuleRole(
                String.valueOf(divisionTemplateLoan.getRepayTemplateId()));
        //investRolelist.addAll(repayRolelist);
        //???(??)

        if (DivisionWayEnum.SIT_WAY.getCode().equals(loan.getRepayDivisionWay())) {
            addDetailDivisionRule(detail, trade, investRolelist);
            addDetailDivisionRule(detail, trade, repayRolelist);
        } else if (DivisionWayEnum.MONTH_WAY.getCode().equals(loan.getRepayDivisionWay())) { // ?
            addDetailDivisionRule(detail, trade, investRolelist);
            addDetailMonthInterestRule(detail, trade, repayRolelist);
        }
    }

    /**
     * ??
     * @param detail
     * @throws Exception
     */
    protected void addTradeFlowCode(TradeDetail detail) throws Exception {
        long tradeId = detail.getTradeId();
        long detailId = detail.getId();
        Trade trade = tradeDao.getByTradeIdWithRowLock(tradeId);
        //??
        LoanDemandDO loan = loanDemandManager.queryLoanDemandByDemandId(trade.getDemandId());
        TradeFlowCode tradeFlow = new TradeFlowCode();
        tradeFlow.setTblBaseId(BusinessNumberUtil.gainNumber());
        tradeFlow.setTradeDetailId(detailId);
        long countIndex = tradeDao.countInvestedTransactions(tradeId);
        tradeFlow.setTradeFlowCode(
                loan.getGuaranteeLicenseNo() + "T" + StringUtils.leftPad(String.valueOf(countIndex), 3, "0"));
        tradeFlow.setRowAddTime(new Date());
        tradeFlow.setNote("??");
        tradeDao.addTradeFlowCode(tradeFlow);
    }

    /**
     * ??
     * @param detail 
     * @throws Exception
     */
    protected void notifyLoanerIfFull(TradeDetail detail) throws Exception {

        Trade trade = tradeDao.getByTradeIdWithRowLock(detail.getTradeId());

        LoanDemandDO loan = loanDemandManager.queryLoanDemandByDemandId(trade.getDemandId());

        //      long gainedAmount1 = trade.getLoanedAmount() + detail.getAmount();
        long tradeFullAmount = 0L;
        if (TradeFullConditionEnum.AMOUNT.code().equals(trade.getSaturationConditionMethod())) {
            tradeFullAmount = Long.valueOf(trade.getSaturationCondition());
        } else if (TradeFullConditionEnum.PERCENTAGE.code().equals(trade.getSaturationConditionMethod())) {
            tradeFullAmount = Math.round(trade.getAmount() * Double.valueOf(trade.getSaturationCondition()));
        }
        if (trade.getLoanedAmount() >= tradeFullAmount) {

            //?
            createRelativeTrades(trade);
            //??
            tradeFinish(trade);

            //??
            List<UserBaseInfoDO> loaners = userBaseInfoManager.queryByType(null,
                    String.valueOf(loan.getLoanerId()));
            StringBuilder toLoanerMessage = new StringBuilder();
            if (loaners != null && loaners.size() > 0) {
                String content = YrdConstants.MessageNotifyConstants.LOAN_DEMAND_INVESTED_CONTENT;
                //            content = content.replace("productName", AppConstantsUtil.getProductName());
                content = content.replace("var1", trade.getName());
                content = content.replace("var2", MoneyUtil.getFormatAmount(trade.getAmount()));
                content = content.replace("var3", MoneyUtil.getFormatAmount(trade.getLoanedAmount()));
                //               MoneyUtil.getFormatAmount(trade.getLoanedAmount() + detail.getAmount()));
                toLoanerMessage.append(content);
                messageService.notifyUser(loaners.get(0), toLoanerMessage.toString());
            }

            // ??
            StringBuilder message = new StringBuilder();
            String content = YrdConstants.MessageNotifyConstants.DEMAND_CONFIRMED_NOTIFY;
            UserBaseInfoDO toUser = new UserBaseInfoDO();
            content = content.replace("var1", trade.getName());
            content = content.replace("var2", MoneyUtil.getFormatAmount(trade.getAmount()));
            content = content.replace("var3", MoneyUtil.getFormatAmount(trade.getLoanedAmount()));
            message.append(content);
            setToUserDetail(toUser);
            messageService.notifyUser(toUser, message.toString());
        }
    }

    private void addDetailDivisionRule(TradeDetail detail, Trade trade, List<DivsionRuleRole> investRolelist)
            throws Exception {
        for (DivsionRuleRole divsionRuleRole : investRolelist) {
            if (SysUserRoleEnum.MARKETING.code().equals(String.valueOf(divsionRuleRole.getRoleId()))) {
                addMarketingRelationUser(detail, trade, divsionRuleRole);
            } else if (SysUserRoleEnum.BROKER.code().equals(String.valueOf(divsionRuleRole.getRoleId()))) {
                addBrokerRelationUser(detail, trade, divsionRuleRole);
            } else if (SysUserRoleEnum.INVESTOR.code().equals(String.valueOf(divsionRuleRole.getRoleId()))) {
                addInvestor(detail, trade, divsionRuleRole);
            } else if (SysUserRoleEnum.PLATFORM.code().equals(String.valueOf(divsionRuleRole.getRoleId()))) {
                if (divsionRuleRole.getRule() > 0) {
                    //               addPlatform(detail, trade, divsionRuleRole);
                }
            }
        }
    }

    private void addDetailMonthInterestRule(TradeDetail detail, Trade trade, List<DivsionRuleRole> repayRolelist)
            throws Exception {
        for (DivsionRuleRole divsionRuleRole : repayRolelist) {
            if (SysUserRoleEnum.MARKETING.code().equals(String.valueOf(divsionRuleRole.getRoleId()))) {
                addMarketingRelationUser(detail, trade, divsionRuleRole);
            } else if (SysUserRoleEnum.BROKER.code().equals(String.valueOf(divsionRuleRole.getRoleId()))) {
                addBrokerRelationUser(detail, trade, divsionRuleRole);
            } else if (SysUserRoleEnum.INVESTOR.code().equals(String.valueOf(divsionRuleRole.getRoleId()))) {
                // addInvestor(detail, trade, divsionRuleRole);
                addInvestorByMonthInterest(detail, trade, divsionRuleRole);
            }
        }

    }

    private void addInvestorByMonthInterest(TradeDetail detail, Trade trade, DivsionRuleRole divsionRuleRole) {
        int monthes = trade.getTimeLimit();

        double investAmount = 0;
        long tradeId = trade.getId();
        long detailId = detail.getId();
        BigDecimal bg = new BigDecimal(getDaysRuleRate(divsionRuleRole.getRule(), trade) * detail.getAmount());
        investAmount = bg.setScale(10, BigDecimal.ROUND_HALF_UP).doubleValue();
        double monthMoney = investAmount / monthes;
        // investAmount = Math.floor(investAmount);
        monthMoney = Math.floor(monthMoney);

        for (int i = 0; i < monthes; i++) {
            TradeDetail tradeDetail = new TradeDetail(detail.getUserId(), tradeId, (long) monthMoney, 12,
                    divsionRuleRole.getPhase(), String.valueOf(detailId));
            tradeDetail.setRepayPeriodNo(i + 1);
            tradeDetail.setRepayPeriodCount(monthes);
            tradeDetailDao.addTradeDetail(tradeDetail);
        }
    }

    private void addPlatform(TradeDetail detail, Trade trade, DivsionRuleRole divsionRuleRole) {
        double platformAmount = 0;
        long tradeId = trade.getId();
        long detailId = detail.getId();
        BigDecimal bg = new BigDecimal(getDaysRuleRate(divsionRuleRole.getRule(), trade) * trade.getLoanedAmount());
        platformAmount = bg.setScale(10, BigDecimal.ROUND_HALF_UP).doubleValue();
        platformAmount = Math.floor(platformAmount);
        // 
        if (platformAmount > 0) {
            UserBaseInfoDO profitUser = userBaseInfoManager
                    .queryByAccountId(AppConstantsUtil.getProfitSharingAccount());
            tradeDetailDao.addTradeDetail(new TradeDetail(profitUser.getUserId(), tradeId, (long) platformAmount, 7,
                    divsionRuleRole.getPhase(), String.valueOf(detailId)));
        }
    }

    private void addInvestor(TradeDetail detail, Trade trade, DivsionRuleRole divsionRuleRole) {
        double investAmount = 0;
        long tradeId = trade.getId();
        long detailId = detail.getId();
        BigDecimal bg = new BigDecimal(getDaysRuleRate(divsionRuleRole.getRule(), trade) * detail.getAmount());
        investAmount = bg.setScale(10, BigDecimal.ROUND_HALF_UP).doubleValue();
        investAmount = Math.floor(investAmount);
        // 
        if (investAmount > 0)
            tradeDetailDao.addTradeDetail(new TradeDetail(detail.getUserId(), tradeId, (long) investAmount, 12,
                    divsionRuleRole.getPhase(), String.valueOf(detailId)));
    }

    private void addBrokerRelationUser(TradeDetail detail, Trade trade, DivsionRuleRole divsionRuleRole)
            throws Exception {
        long detailId = detail.getId();
        long tradeId = trade.getId();
        Page<UserRelationDO> userRelationsPage = userRelationManager.getRelationsByConditions(null, null,
                detail.getUserId(), null);

        UserBaseInfoDO jjrUserBaseInfo = null;
        if (ListUtil.isNotEmpty(userRelationsPage.getResult())) {
            UserRelationDO relationDO = userRelationsPage.getResult().get(0);
            List<UserBaseInfoDO> curParentJjrs = userBaseInfoManager.queryByType(null,
                    String.valueOf(relationDO.getParentId()));
            if (ListUtil.isNotEmpty(curParentJjrs)) {
                if (UserTypeEnum.GR.code().equals(curParentJjrs.get(0).getType())) {
                    jjrUserBaseInfo = curParentJjrs.get(0);
                }
            }
            if (jjrUserBaseInfo == null && this.sysFunctionConfigService.isAllEconomicMan()) {
                jjrUserBaseInfo = userBaseInfoManager.queryByUserId(detail.getUserId());
            }
        }
        if (jjrUserBaseInfo != null) {
            ProfitAsignInfo profitAsignInfo = userRelationManager
                    .queryByReceiveIdAndDistributionId(detail.getUserId(), jjrUserBaseInfo.getUserId());
            double distributionRule = 0;
            double distributionAmount = 0;
            if (profitAsignInfo != null) {
                distributionRule = CommonUtil.mul(divsionRuleRole.getRule(),
                        profitAsignInfo.getDistributionQuota());
            }
            double actualRule = divsionRuleRole.getRule() - distributionRule;
            BigDecimal bg = new BigDecimal(getDaysRuleRate(actualRule, trade) * detail.getAmount());
            double jjrAmount = bg.setScale(10, BigDecimal.ROUND_HALF_UP).doubleValue();
            jjrAmount = Math.floor(jjrAmount);
            if (distributionRule > 0) {
                BigDecimal bgdis = new BigDecimal(getDaysRuleRate(distributionRule, trade) * detail.getAmount());
                distributionAmount = bgdis.setScale(10, BigDecimal.ROUND_HALF_UP).doubleValue();
                distributionAmount = Math.floor(distributionAmount);
                //???
                TradeDetail extraDetail = new TradeDetail(detail.getUserId(), tradeId, (long) distributionAmount,
                        12, divsionRuleRole.getPhase(), String.valueOf(detailId));
                extraDetail.setProfitType(1);
                extraDetail.setProfitRate(distributionRule);
                tradeDetailDao.addTradeDetail(extraDetail);
            }

            //?
            tradeDetailDao.addTradeDetail(new TradeDetail(jjrUserBaseInfo.getUserId(), tradeId, (long) jjrAmount,
                    11, divsionRuleRole.getPhase(), String.valueOf(detailId)));
        }

    }

    private void addMarketingRelationUser(TradeDetail detail, Trade trade, DivsionRuleRole divsionRuleRole)
            throws Exception {
        double yxJGAmount = 0;
        BigDecimal bg = new BigDecimal(getDaysRuleRate(divsionRuleRole.getRule(), trade) * detail.getAmount());
        yxJGAmount = bg.setScale(10, BigDecimal.ROUND_HALF_UP).doubleValue();
        yxJGAmount = Math.floor(yxJGAmount);

        UserBaseInfoDO curParentJjr = null;
        if (curParentJjr == null) {
            try {
                curParentJjr = userBaseInfoManager.queryByUserName(detail.getUserName(),
                        SysUserRoleEnum.BROKER.getValue());
            } catch (Exception e) {
                logger.error(e.getMessage(), e);
            }
        }
        if (curParentJjr == null) {
            Page<UserRelationDO> userRelationsPage = userRelationManager.getRelationsByConditions(null, null,
                    detail.getUserId(), null);
            if (userRelationsPage.getResult() != null && userRelationsPage.getResult().size() > 0) {
                List<UserBaseInfoDO> curParentJjrs = userBaseInfoManager.queryByType(null,
                        String.valueOf(userRelationsPage.getResult().get(0).getParentId()));
                if (curParentJjrs != null && curParentJjrs.size() > 0) {
                    if (UserTypeEnum.GR.code().equals(curParentJjrs.get(0).getType())) {
                        curParentJjr = curParentJjrs.get(0);
                    }

                }
            }
        }
        if (curParentJjr != null) {
            //??
            UserBaseInfoDO curParentJG = null;
            int maxLength = 20;
            int index = 0;
            long curParentJjrUserId = curParentJjr.getUserId();
            while (curParentJG == null && index < maxLength) {
                index++;
                Page<UserRelationDO> userRelationsJGPage = userRelationManager.getRelationsByConditions(null, null,
                        curParentJjrUserId, null);
                if (userRelationsJGPage.getResult() != null && userRelationsJGPage.getResult().size() > 0) {
                    long parentUserId = userRelationsJGPage.getResult().get(0).getParentId();
                    UserBaseInfoDO parentUser = userBaseInfoManager.queryByUserId(parentUserId);
                    if (parentUser != null) {
                        if (UserTypeEnum.JG.code().equals(parentUser.getType())) {
                            curParentJG = parentUser;
                            break;
                        } else {
                            curParentJjrUserId = parentUser.getUserId();
                        }
                    }
                } else {
                    break;
                }
            }
            if (curParentJG != null) {
                //?
                tradeDetailDao.addTradeDetail(new TradeDetail(curParentJG.getUserId(), trade.getId(),
                        (long) yxJGAmount, 10, divsionRuleRole.getPhase(), String.valueOf(detail.getId())));
            }

        }

        //      double yxJGAmount = 0;
        //      long tradeId = trade.getId();
        //      long detailId = detail.getId();
        //      BigDecimal bg = new BigDecimal(getDaysRuleRate(
        //            divsionRuleRole.getRule(), trade)
        //            * detail.getAmount());
        //      yxJGAmount = bg.setScale(10, BigDecimal.ROUND_HALF_UP).doubleValue();
        //      yxJGAmount = Math.floor(yxJGAmount);
        //      // ??
        //      Page<UserRelationDO> userRelationsPage = userRelationManager
        //            .getRelationsByConditions(null, null, detail.getUserId(), null);
        //      if (userRelationsPage.getResult() != null
        //            && userRelationsPage.getResult().size() > 0) {
        //         List<UserBaseInfoDO> curParentJjrs = userBaseInfoManager
        //               .queryByType(
        //                     null,
        //                     String.valueOf(userRelationsPage.getResult().get(0)
        //                           .getParentId()));
        //         UserBaseInfoDO curParentJjr = null;
        //         if (curParentJjrs != null && curParentJjrs.size() > 0) {
        //            curParentJjr = curParentJjrs.get(0);
        //            // ??
        //            Page<UserRelationDO> userRelationsJGPage = userRelationManager
        //                  .getRelationsByConditions(null, null,
        //                        curParentJjr.getUserId(), null);
        //            if (userRelationsJGPage.getResult() != null
        //                  && userRelationsJGPage.getResult().size() > 0) {
        //               List<UserBaseInfoDO> curParentJGs = userBaseInfoManager
        //                     .queryByType(
        //                           UserTypeEnum.JG.code(),
        //                           String.valueOf(userRelationsJGPage
        //                                 .getResult().get(0).getParentId()));
        //               UserBaseInfoDO curParentJG = null;
        //               if (curParentJGs != null && curParentJGs.size() > 0) {
        //                  curParentJG = curParentJGs.get(0);
        //                  // ?
        //                  tradeDetailDao.addTradeDetail(new TradeDetail(
        //                        curParentJG.getUserId(), tradeId,
        //                        (long) yxJGAmount, 10, divsionRuleRole
        //                              .getPhase(), String.valueOf(detailId)));
        //               }
        //            }
        //         }
        //      }
    }

    /**
     * 
     * @param trade
     * @return
     */
    private Map<String, Object> doCheckTrade(Trade trade) {
        Map<String, Object> result = new HashMap<String, Object>();
        result.put("status", false);
        if (trade == null) {
            result.put("message", "");
            return result;
        }
        if (trade.getStatus() != YrdConstants.TradeStatus.TRADING) {
            result.put("message", "??");
        } else {
            result.put("status", true);
        }
        return result;
    }

    /**
     * ?
     * @param amount
     * @return
     */
    private Map<String, Object> doCheckAmount(Trade trade, String userId, Long amount) {
        Map<String, Object> result = new HashMap<String, Object>();
        result.put("status", false);
        if (amount == null || amount <= 0) {
            result.put("message", "?0");
            return result;
        }

        if ((trade.getLeastInvestAmount() - (trade.getAmount() - trade.getLoanedAmount())) <= 0) {
            if (amount < trade.getLeastInvestAmount()) {
                result.put("message", "????");
                return result;
            }
        }

        if (trade.getLoanedAmount() + amount > trade.getAmount()) {
            result.put("message", "????");
            return result;
        }
        YzzUserAccountQueryRequest queryRequest = new YzzUserAccountQueryRequest(userId);
        YzzUserAccountQueryResponse accountResult = openApiGatewayService.userAccountQuery(queryRequest);
        if (!accountResult.success()) {
            result.put("message", "?");
            return result;
        }

        result.put("status", true);
        return result;
    }

    @Override
    public List<InvestDetailDO> queryInvestDetail(Map<String, Object> condition) {
        return tradeDetailDao.queryInvestDetail(condition);
    }

    @Override
    public void updateInvestDetailRepayDate(long detailId, Date repayDate) {
        tradeDetailDao.updateRepaydate(detailId, repayDate);
    }

    public static void main(String[] args) {
        int days = 56;
        Calendar endTime = Calendar.getInstance();
        Calendar beginTime = Calendar.getInstance();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date date = null;
        try {
            date = sdf.parse("2015-01-27 09:49:21");
        } catch (ParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        beginTime.setTime(date);
        int cutDays = (int) ((endTime.getTimeInMillis() - beginTime.getTimeInMillis()) / 1000 / 60 / 60 / 24);
        days = days - cutDays;
        days = (days < 0 ? 0 : days);
        System.out.println("cutDays: " + cutDays);
        System.out.println("days: " + days);
    }

}