RationBiz.java 12.8 KB
package com.cjs.cms.biz.ration;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.cjs.cms.biz.user.fund.UserFinanceBiz;
import com.cjs.cms.dao.ration.RationNewConfigDao;
import com.cjs.cms.dao.ration.RationNewRecordDao;
import com.cjs.cms.dao.ration.RationNewUserDao;
import com.cjs.cms.dao.ration.TrustApplyExtDao;
import com.cjs.cms.dao.user.MemberDao;
import com.cjs.cms.model.pub.ConstInfo;
import com.cjs.cms.model.pub.ResultInfo;
import com.cjs.cms.model.ration.RationNewConfigInfo;
import com.cjs.cms.model.ration.RationNewRecordInfo;
import com.cjs.cms.model.ration.RationNewUserInfo;
import com.cjs.cms.model.ration.TrustApplyExtInfo;
import com.cjs.cms.util.t2.T2Result;
import com.cjs.cms.util.web.ActionUtil;

/**
 * 新品配售
 * 
 * @author tongyufu
 *
 */
@Service
public class RationBiz {

    Logger                     log = LogManager.getLogger();
    @Autowired
    private RationNewConfigDao rationNewConfigDao;
    @Autowired
    private RationNewUserDao   rationNewUserDao;
    @Autowired
    private RationNewRecordDao rationNewRecordDao;
    @Autowired
    private TrustApplyExtDao   trustApplyExtDao;
    @Autowired
    private UserFinanceBiz     userFinanceBiz;
    @Autowired
    private MemberDao          memberDao;
    @Autowired
    private StorageBiz         storageBiz;

    /**
     * 开始配售
     */
    public ResultInfo ration(Integer configId) {
        RationNewConfigInfo configInfo = rationNewConfigDao.queryById(configId);
        String message;

        try {
            if (configInfo == null) {
                return new ResultInfo(4, "配售设置信息不存在");
            }
            //配售方式(0:不配售直接上市;1:配售)
            if (!"1".equals(configInfo.getRationType())) {
                return new ResultInfo(4, "该藏品不参与配售");
            }
            //            if (StringUtil.equals(configInfo.getRationStatus(), "3", "4")) {
            //                return new ResultInfo(4, "只能执行待配售的任务");
            //            }
            configInfo.setRationStatus("2");
            rationNewConfigDao.update(configInfo);
            if ("1".equals(configInfo.getNeedConfirm())
                && configInfo.getConfirmEndDate().getTime() > new Date().getTime()) {
                return this.rationResult(1, "用户确认配售日期尚未截止,不可以配售", configInfo);
            }
            List<RationNewUserInfo> rationNewUsers = rationNewUserDao.queryByConfigId(configId);
            if (rationNewUsers.isEmpty()) {
                return this.rationResult(1, "该配售设置信息下没有用户", configInfo);
            }
            Integer aggreeCount = trustApplyExtDao.queryAggreeCount(configInfo.getOtcCode());
            if (aggreeCount == null || aggreeCount == 0) {
                return this.rationResult(1, "用户同意分配的数量为0", configInfo);
            }
            //校验用户资金是否足额,假设3%的藏品会配售给内部账户
            /*
            Map<String, Object> balance = userFinanceBiz.balance(configInfo.getInnerAccount());
            Double needMoney = aggreeCount * 0.03 * configInfo.getPrice();
            Double enableBalance = Double.parseDouble(balance.get("enable_balance").toString());
            if (needMoney > enableBalance) {
                message = MessageFormat.format("用户[{0}]资金不足。可用余额:[{1}],需要[{2}]",
                    configInfo.getInnerAccount(), enableBalance, needMoney);
                return this.rationResult(1, message, configInfo);
            }*/

            //配售给机构总比例
            Double totalPercent = 0d;
            for (RationNewUserInfo rationNewUserInfo : rationNewUsers) {
                Map<String, Object> balance = userFinanceBiz.balance(rationNewUserInfo.getUserId());
                Double needMoney = new BigDecimal(rationNewUserInfo.getPercent())
                    .divide(new BigDecimal(100)).multiply(new BigDecimal(aggreeCount))
                    .setScale(0, RoundingMode.HALF_UP)
                    .multiply(new BigDecimal(configInfo.getPrice())).doubleValue();
                Double enableBalance = Double.parseDouble(balance.get("enable_balance").toString());
                if (needMoney > enableBalance) {
                    message = MessageFormat.format("用户[{0}]资金不足。可用余额:[{1}],需要[{2}]",
                        rationNewUserInfo.getUserId(), enableBalance, needMoney);
                    return this.rationResult(1, message, configInfo);
                }
                totalPercent += rationNewUserInfo.getPercent();
            }

            //获取配售用户列表
            List<TrustApplyExtInfo> trustApplies = trustApplyExtDao
                .queryAggreeList(configInfo.getOtcCode());
            for (TrustApplyExtInfo trustApply : trustApplies) {
                rationTrust(configInfo, rationNewUsers, trustApply, totalPercent);
            }

            //配售结果
            if (rationNewRecordDao.queryRecordCount(configId, "0") > 0) {
                return this.rationResult(4, "配售部分成功", configInfo);
            }
            return this.rationResult(3, "配售成功", configInfo);
        } catch (Exception e) {
            log.error("配售失败", e);
            return this.rationResult(4, e.getMessage(), configInfo);
        }
    }

    /**
     * 配售单个托管申请
     * @param configInfo 配售设置
     * @param rationNewUsers 配售用户
     * @param innerOtcAccount 内置账号的股东账户
     * @param trustApply 托管申请
     * @param totalPercent 配售给机构总比例
     */
    private void rationTrust(RationNewConfigInfo configInfo, List<RationNewUserInfo> rationNewUsers,
                             TrustApplyExtInfo trustApply, Double totalPercent) {
        //配售状态(0:配售失败;1:待交割;2:已入库)
        try {
            List<T2Result> results = new ArrayList<T2Result>();
            String sellOtcAccount = memberDao.queryOtcAccount(trustApply.getFundAccount());
            RationNewRecordInfo record = new RationNewRecordInfo();
            record.setRationNewConfigId(configInfo.getId());
            record.setSellUserId(trustApply.getFundAccount());
            record.setSellOtcAccount(sellOtcAccount);
            record.setApplyNo(trustApply.getApplyNo());
            record.setPreInStatus("0");
            record.setApprovalAcount(trustApply.getApprovalCount());
            record.setRegistration("0");
            record.setRationStatus("1");
            record.setCreateBy(ActionUtil.getUser().getUsername());

            if (!"1".equals(trustApply.getAggreeStatus())) {
                record.setRationStatus("0");
                record.setRemark("该托管单状态不是同意配售");
                rationNewRecordDao.save(record);
                return;
            }
            if (trustApply.getApprovalCount() <= 0) {
                record.setRationStatus("0");
                record.setRemark("该托管单鉴定通过数量为0");
                rationNewRecordDao.save(record);
                return;
            }
            if (!"4".equals(trustApply.getApplyType()) && !"5".equals(trustApply.getApplyType())) {
                record.setRationStatus("0");
                record.setRemark("该托管单鉴定状态为" + trustApply.getApplyType());
                rationNewRecordDao.save(record);
                return;
            }

            //配售给机构的总量
            int rationTotal = new BigDecimal(totalPercent).divide(new BigDecimal(100))
                .multiply(new BigDecimal(trustApply.getApprovalCount()))
                .setScale(0, RoundingMode.HALF_UP).intValue();
            //配售给托管方数量
            int trustTotal = trustApply.getApprovalCount() - rationTotal;
            int rationCount;
            double money;
            //配售给机构
            for (Iterator<RationNewUserInfo> it = rationNewUsers.iterator(); it.hasNext();) {
                RationNewUserInfo rationNewUserInfo = it.next();
                //配售数量。如果是最后一个机构,则获得配售量为:鉴定通过数量 * 所有机构配售比例总和 - 除去最后一个机构的已配售数量
                if (it.hasNext()) {
                    rationCount = new BigDecimal(rationNewUserInfo.getPercent())
                        .divide(new BigDecimal(100))
                        .multiply(new BigDecimal(trustApply.getApprovalCount()))
                        .setScale(0, RoundingMode.HALF_UP).intValue();
                    rationTotal -= rationCount;
                } else {
                    rationCount = rationTotal;
                }
                if (rationCount <= 0) {
                    continue;
                }
                money = rationCount * configInfo.getPrice();
                record.setRationNewUserId(rationNewUserInfo.getId());
                record.setBuyUserId(rationNewUserInfo.getUserId());
                record.setBuyOtcAccount(rationNewUserInfo.getOtcAccount());
                record.setFund(money);
                record.setStockAmount(rationCount);
                rationNewRecordDao.save(record);
                if (money > 0.0) {
                    results = userFinanceBiz.pay(record.getId().toString(),
                        ConstInfo.Fund.NEW_RATION, rationNewUserInfo.getUserId(),
                        trustApply.getFundAccount(), money, ConstInfo.Fund.NEW_RATION_REMARK);
                    this.payResult(results, record);
                    rationNewRecordDao.updateById(record);
                }
            }

            //配售给托管用户
            if (trustTotal >= 0) {
                record.setBuyUserId(trustApply.getFundAccount());
                record.setBuyOtcAccount(sellOtcAccount);
                record.setFund(0d);
                record.setStockAmount(trustTotal);
                rationNewRecordDao.save(record);
            }

            //配售给内置账户
            /*
            rationCount = rationTotal - rationCount;
            if (rationCount > 0) {
                money = rationCount * configInfo.getPrice();
                record.setBuyUserId(configInfo.getInnerAccount());
                record.setBuyOtcAccount(innerOtcAccount);
                record.setFund(money);
                record.setStockAmount(rationCount);
                rationNewRecordDao.save(record);
                results = userFinanceBiz.pay(record.getId().toString(),
                    ConstInfo.Fund.NEW_RATION, configInfo.getInnerAccount(),
                    trustApply.getFundAccount(), money, ConstInfo.Fund.NEW_RATION_REMARK);
                this.payResult(results, record);
                rationNewRecordDao.updateById(record);
            }*/

            //入库
            if ("5".equals(trustApply.getApplyType())) {
                record.setPreInStatus("1");
            }
            if ("4".equals(trustApply.getApplyType())) {
                T2Result result = storageBiz.storage(trustApply.getApplyNo());
                if (result.getCode() == 0) {
                    record.setPreInStatus("1");
                } else {
                    record.setRationStatus("0");
                }
            }
            rationNewRecordDao.updateByApplyNo(record);
            trustApplyExtDao.updateAggreeStatus(trustApply.getApplyNo(), "2");
        } catch (Exception e) {
            trustApplyExtDao.updateAggreeStatus(trustApply.getApplyNo(), "0");
            log.error("配售出错:" + trustApply.getApplyNo(), e);
        }
    }

    /**处理支付结果*/
    private RationNewRecordInfo payResult(List<T2Result> results, RationNewRecordInfo record) {
        if (results.size() == 1) {
            record.setRemark(results.get(0).toString());
            record.setRationStatus("0");
            trustApplyExtDao.updateAggreeStatus(record.getApplyNo(), "0");
        } else {
            StringBuilder sb = new StringBuilder();
            for (T2Result result : results) {
                sb.append(result.toString()).append("|");
            }
            record.setRemark(sb.toString());
        }
        return record;
    }

    /**返回配售结果信息*/
    private ResultInfo rationResult(Integer code, String message, RationNewConfigInfo configInfo) {
        ResultInfo resultInfo = new ResultInfo();
        resultInfo.setCode(code);
        resultInfo.setMessage(message);
        configInfo.setRationStatus(code.toString());
        configInfo.setRationResult(message);
        rationNewConfigDao.update(configInfo);
        return resultInfo;
    }
}