From 79e81397b1bf90e6833db97e4944f8fe7801a669 Mon Sep 17 00:00:00 2001
From: Helius <wangdoubleone@gmail.com>
Date: Fri, 31 Jul 2020 17:04:24 +0800
Subject: [PATCH] add submit follower order

---
 src/main/java/com/xcong/excoin/modules/documentary/dao/FollowFollowerOrderRelationDao.java           |    3 
 src/main/java/com/xcong/excoin/modules/documentary/dao/FollowTraderInfoDao.java                      |    2 
 src/main/java/com/xcong/excoin/modules/documentary/service/FollowOrderOperationService.java          |   13 ++
 src/main/java/com/xcong/excoin/modules/documentary/service/impl/FollowOrderOperationServiceImpl.java |  199 +++++++++++++++++++++++++++++++++++++++
 src/main/java/com/xcong/excoin/modules/documentary/dao/FollowFollowerSettingDao.java                 |    4 
 src/main/java/com/xcong/excoin/modules/documentary/common/NoticeConstant.java                        |   13 ++
 src/main/resources/mapper/documentary/FollowFollowerSettingDao.xml                                   |    7 +
 src/main/resources/mapper/documentary/FollowTraderInfoDao.xml                                        |    6 +
 src/main/java/com/xcong/excoin/utils/LogRecordUtils.java                                             |   20 +++
 src/main/resources/mapper/documentary/FollowFollowerOrderRelationDao.xml                             |    8 +
 10 files changed, 273 insertions(+), 2 deletions(-)

diff --git a/src/main/java/com/xcong/excoin/modules/documentary/common/NoticeConstant.java b/src/main/java/com/xcong/excoin/modules/documentary/common/NoticeConstant.java
new file mode 100644
index 0000000..aae8da4
--- /dev/null
+++ b/src/main/java/com/xcong/excoin/modules/documentary/common/NoticeConstant.java
@@ -0,0 +1,13 @@
+package com.xcong.excoin.modules.documentary.common;
+
+/**
+ * @author wzy
+ * @date 2020-07-31
+ **/
+public class NoticeConstant {
+
+    public static final String OPEN_ORDER_TITLE = "跟单开仓成功";
+
+    public static final String OPEN_ORDER_CONTENT = "{}开仓成功,开仓价{},交易员{}";
+
+}
diff --git a/src/main/java/com/xcong/excoin/modules/documentary/dao/FollowFollowerOrderRelationDao.java b/src/main/java/com/xcong/excoin/modules/documentary/dao/FollowFollowerOrderRelationDao.java
index dff3af5..a6c1a0e 100644
--- a/src/main/java/com/xcong/excoin/modules/documentary/dao/FollowFollowerOrderRelationDao.java
+++ b/src/main/java/com/xcong/excoin/modules/documentary/dao/FollowFollowerOrderRelationDao.java
@@ -2,9 +2,12 @@
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.xcong.excoin.modules.documentary.entity.FollowFollowerOrderRelationEntity;
+import io.lettuce.core.dynamic.annotation.Param;
 
 /**
  * @author helius
  */
 public interface FollowFollowerOrderRelationDao extends BaseMapper<FollowFollowerOrderRelationEntity> {
+
+    Integer selectFollowerHoldingSymbolCnt(@Param("tradeMemberId") Long tradeMemberId, @Param("memberId") Long memberId);
 }
diff --git a/src/main/java/com/xcong/excoin/modules/documentary/dao/FollowFollowerSettingDao.java b/src/main/java/com/xcong/excoin/modules/documentary/dao/FollowFollowerSettingDao.java
index aa057fc..f1c028a 100644
--- a/src/main/java/com/xcong/excoin/modules/documentary/dao/FollowFollowerSettingDao.java
+++ b/src/main/java/com/xcong/excoin/modules/documentary/dao/FollowFollowerSettingDao.java
@@ -5,6 +5,8 @@
 
 import io.lettuce.core.dynamic.annotation.Param;
 
+import java.util.List;
+
 /**
  * @author helius
  */
@@ -13,4 +15,6 @@
 	FollowFollowerSettingEntity selectDocumentaryOrderSetInfoBymemberId(@Param("memberId")Long memberId);
 
 	FollowFollowerSettingEntity selectOneBymemberIdAndTradeId(@Param("memberId")Long memberId, @Param("traderId")Long traderId);
+
+	List<FollowFollowerSettingEntity> selectAllFollowerSettingByTradeMemberId(@Param("memberId") Long memberId);
 }
diff --git a/src/main/java/com/xcong/excoin/modules/documentary/dao/FollowTraderInfoDao.java b/src/main/java/com/xcong/excoin/modules/documentary/dao/FollowTraderInfoDao.java
index 2e452cd..6daeec0 100644
--- a/src/main/java/com/xcong/excoin/modules/documentary/dao/FollowTraderInfoDao.java
+++ b/src/main/java/com/xcong/excoin/modules/documentary/dao/FollowTraderInfoDao.java
@@ -9,4 +9,6 @@
 
 	FollowTraderInfoEntity selectFollowTraderInfoEntityBytreaderId(@Param("traderId")Long traderId);
 
+	FollowTraderInfoEntity selectTraderInfoByMemberId(@Param("memberId") Long memberId);
+
 }
diff --git a/src/main/java/com/xcong/excoin/modules/documentary/service/FollowOrderOperationService.java b/src/main/java/com/xcong/excoin/modules/documentary/service/FollowOrderOperationService.java
new file mode 100644
index 0000000..2686947
--- /dev/null
+++ b/src/main/java/com/xcong/excoin/modules/documentary/service/FollowOrderOperationService.java
@@ -0,0 +1,13 @@
+package com.xcong.excoin.modules.documentary.service;
+
+
+import com.xcong.excoin.modules.contract.entity.ContractHoldOrderEntity;
+
+/**
+ * @author helius
+ */
+public interface FollowOrderOperationService {
+
+
+    public void addFollowerOrder(Long id);
+}
diff --git a/src/main/java/com/xcong/excoin/modules/documentary/service/impl/FollowOrderOperationServiceImpl.java b/src/main/java/com/xcong/excoin/modules/documentary/service/impl/FollowOrderOperationServiceImpl.java
new file mode 100644
index 0000000..93c91f9
--- /dev/null
+++ b/src/main/java/com/xcong/excoin/modules/documentary/service/impl/FollowOrderOperationServiceImpl.java
@@ -0,0 +1,199 @@
+package com.xcong.excoin.modules.documentary.service.impl;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.StrUtil;
+import com.alibaba.fastjson.JSONObject;
+import com.xcong.excoin.common.enumerates.CoinTypeEnum;
+import com.xcong.excoin.common.enumerates.RabbitPriceTypeEnum;
+import com.xcong.excoin.common.response.Result;
+import com.xcong.excoin.common.system.service.CommonService;
+import com.xcong.excoin.modules.contract.dao.ContractHoldOrderDao;
+import com.xcong.excoin.modules.contract.dao.ContractOrderDao;
+import com.xcong.excoin.modules.contract.entity.ContractEntrustOrderEntity;
+import com.xcong.excoin.modules.contract.entity.ContractHoldOrderEntity;
+import com.xcong.excoin.modules.contract.entity.ContractOrderEntity;
+import com.xcong.excoin.modules.contract.mapper.ContractHoldOrderEntityMapper;
+import com.xcong.excoin.modules.documentary.common.NoticeConstant;
+import com.xcong.excoin.modules.documentary.dao.FollowFollowerOrderRelationDao;
+import com.xcong.excoin.modules.documentary.dao.FollowFollowerProfitDao;
+import com.xcong.excoin.modules.documentary.dao.FollowFollowerSettingDao;
+import com.xcong.excoin.modules.documentary.dao.FollowTraderInfoDao;
+import com.xcong.excoin.modules.documentary.entity.FollowFollowerProfitEntity;
+import com.xcong.excoin.modules.documentary.entity.FollowFollowerSettingEntity;
+import com.xcong.excoin.modules.documentary.entity.FollowTraderInfoEntity;
+import com.xcong.excoin.modules.documentary.service.FollowOrderOperationService;
+import com.xcong.excoin.modules.member.dao.MemberDao;
+import com.xcong.excoin.modules.member.dao.MemberWalletContractDao;
+import com.xcong.excoin.modules.member.entity.AgentReturnEntity;
+import com.xcong.excoin.modules.member.entity.MemberEntity;
+import com.xcong.excoin.modules.member.entity.MemberWalletContractEntity;
+import com.xcong.excoin.modules.platform.entity.PlatformTradeSettingEntity;
+import com.xcong.excoin.rabbit.pricequeue.OrderModel;
+import com.xcong.excoin.rabbit.producer.OrderProducer;
+import com.xcong.excoin.utils.CacheSettingUtils;
+import com.xcong.excoin.utils.CalculateUtil;
+import com.xcong.excoin.utils.LogRecordUtils;
+import com.xcong.excoin.utils.ThreadPoolUtils;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * @author helius
+ */
+@Slf4j
+@Service
+public class FollowOrderOperationServiceImpl implements FollowOrderOperationService {
+
+    @Resource
+    private ContractHoldOrderDao contractHoldOrderDao;
+    @Resource
+    private FollowFollowerSettingDao followFollowerSettingDao;
+    @Resource
+    private CacheSettingUtils cacheSettingUtils;
+    @Resource
+    private FollowFollowerOrderRelationDao followFollowerOrderRelationDao;
+    @Resource
+    private MemberWalletContractDao memberWalletContractDao;
+    @Resource
+    private MemberDao memberDao;
+    @Resource
+    private CommonService commonService;
+    @Resource
+    private ContractOrderDao contractOrderDao;
+    @Resource
+    private OrderProducer producer;
+    @Resource
+    private FollowTraderInfoDao followTraderInfoDao;
+
+    @Override
+    public void addFollowerOrder(Long id) {
+        // 查询交易员订单
+        ContractHoldOrderEntity holdOrderEntity = contractHoldOrderDao.selectById(id);
+
+        List<FollowFollowerSettingEntity> followerSettings = followFollowerSettingDao.selectAllFollowerSettingByTradeMemberId(holdOrderEntity.getMemberId());
+        // 开仓价
+        BigDecimal openPrice = holdOrderEntity.getOpeningPrice();
+        PlatformTradeSettingEntity tradeSettingEntity = cacheSettingUtils.getTradeSetting();
+
+        // 交易员信息
+        FollowTraderInfoEntity followTraderInfoEntity = followTraderInfoDao.selectTraderInfoByMemberId(holdOrderEntity.getMemberId());
+
+        // 点差
+        BigDecimal lotNumber = cacheSettingUtils.getSymbolSku(holdOrderEntity.getSymbol());
+        Long tradeMemberId = holdOrderEntity.getMemberId();
+        if (CollUtil.isNotEmpty(followerSettings)) {
+            for (FollowFollowerSettingEntity followerSetting : followerSettings) {
+                // 当前持仓张数
+                Integer holdingCnt = followFollowerOrderRelationDao.selectFollowerHoldingSymbolCnt(tradeMemberId, followerSetting.getMemberId());
+
+                // 跟单张数 根据跟随者设置,若为固定张数,则为其固定张数,若为固定比例,则与交易员张数相乘。但必须小于最大持仓张数
+                int symbolCnt = 0;
+                if (followerSetting.getFollowType().equals(FollowFollowerSettingEntity.FOLLOW_TYPE_PIECE)) {
+                    symbolCnt = followerSetting.getFollowCnt();
+                } else {
+                    symbolCnt = followerSetting.getFollowCnt() * holdOrderEntity.getSymbolCnt();
+                }
+
+                // 若张数+当前持仓张数大于最大持仓张数,则取最大持仓减去当前持仓,若差值小于等于0,则不下单
+                if (symbolCnt + holdingCnt> followerSetting.getMaxFollowCnt()) {
+                    symbolCnt = followerSetting.getMaxFollowCnt() - holdingCnt;
+                }
+
+                if (symbolCnt <= 0) {
+                    continue;
+                }
+
+                MemberWalletContractEntity walletContract = memberWalletContractDao.findWalletContractByMemberIdAndSymbol(followerSetting.getMemberId(), CoinTypeEnum.USDT.name());
+                if (walletContract == null) {
+                    log.info("钱包地址不存在:{}", followerSetting.getMemberId());
+                    continue;
+                }
+
+                // 开仓手续费 建仓价*规格*手数*手续费率
+                BigDecimal openFeePrice = openPrice.multiply(lotNumber)
+                        .multiply(new BigDecimal(symbolCnt))
+                        .multiply(tradeSettingEntity.getFeeRatio().divide(new BigDecimal(100)))
+                        .setScale(8, BigDecimal.ROUND_DOWN);
+
+                // 保证金
+                BigDecimal bondAmount = openPrice.multiply(lotNumber).multiply(new BigDecimal(symbolCnt))
+                        .multiply(BigDecimal.ONE.divide(new BigDecimal(holdOrderEntity.getLeverRatio())))
+                        .setScale(8, BigDecimal.ROUND_DOWN);
+
+                // 预付款
+                BigDecimal prePaymentAmount = bondAmount.add(openFeePrice).add(openFeePrice);
+                if (prePaymentAmount.compareTo(walletContract.getAvailableBalance()) > -1) {
+                    log.info("可用金额不足");
+                    continue;
+                }
+
+                MemberEntity memberEntity = memberDao.selectById(followerSetting.getMemberId());
+                // 强平价
+                BigDecimal forceClosingPrice = CalculateUtil.getForceSetPrice(bondAmount, openPrice, symbolCnt, lotNumber, holdOrderEntity.getOpeningType(), memberEntity);
+
+                ContractHoldOrderEntity followHoldOrder = new ContractHoldOrderEntity();
+                followHoldOrder.setMemberId(memberEntity.getId());
+                followHoldOrder.setOrderNo(commonService.generateOrderNo(memberEntity.getId()));
+                followHoldOrder.setPositionType(ContractEntrustOrderEntity.POSITION_TYPE_ADD);
+                followHoldOrder.setTradeType(ContractHoldOrderEntity.TRADE_TYPE_MARK);
+                followHoldOrder.setSymbol(holdOrderEntity.getSymbol());
+                followHoldOrder.setSymbolCnt(symbolCnt);
+                followHoldOrder.setSymbolSku(lotNumber);
+                followHoldOrder.setLeverRatio(holdOrderEntity.getLeverRatio());
+                followHoldOrder.setForceClosingPrice(forceClosingPrice);
+                followHoldOrder.setOpeningFeeAmount(openFeePrice);
+                followHoldOrder.setOpeningPrice(openPrice);
+                followHoldOrder.setOpeningType(holdOrderEntity.getOpeningType());
+                followHoldOrder.setMarkPrice(openPrice);
+                followHoldOrder.setIsCanClosing(ContractHoldOrderEntity.ORDER_CAN_CLOSING_Y);
+                followHoldOrder.setPrePaymentAmount(prePaymentAmount);
+                followHoldOrder.setBondAmount(bondAmount.add(openFeePrice));
+                followHoldOrder.setOperateNo(1);
+                // 设置合约类型
+                holdOrderEntity.setContractType(ContractOrderEntity.CONTRACTTYPE_DOCUMENTARY);
+
+                ContractOrderEntity contractOrderEntity = ContractHoldOrderEntityMapper.INSTANCE.holdOrderToOrder(holdOrderEntity);
+                contractOrderEntity.setOpeningTime(new Date());
+                contractHoldOrderDao.insert(holdOrderEntity);
+                int i = contractOrderDao.insert(contractOrderEntity);
+
+                if (i > 0) {
+                    memberWalletContractDao.increaseWalletContractBalanceById(prePaymentAmount.negate(), openFeePrice.negate(), null, walletContract.getId());
+
+                    // 发送爆仓消息
+                    sendOrderBombMsg(holdOrderEntity.getId(), holdOrderEntity.getOpeningType(), forceClosingPrice, holdOrderEntity.getSymbol(), holdOrderEntity.getOperateNo());
+
+                    // 计算佣金
+                    ThreadPoolUtils.calReturnMoney(memberEntity.getId(), contractOrderEntity.getOpeningFeeAmount(), contractOrderEntity, AgentReturnEntity.ORDER_TYPE_OPEN);
+
+                    // 插入财务流水
+                    if (holdOrderEntity.getOpeningType() == ContractHoldOrderEntity.OPENING_TYPE_MORE) {
+                        LogRecordUtils.insertMemberAccountFlow(memberEntity.getId(), prePaymentAmount, walletContract.getAvailableBalance().subtract(prePaymentAmount), holdOrderEntity.getSymbol(), "买涨持仓", "买涨:" + holdOrderEntity.getSymbol());
+                        LogRecordUtils.insertFollowerNotice(memberEntity.getId(), NoticeConstant.OPEN_ORDER_TITLE, StrUtil.format(NoticeConstant.OPEN_ORDER_CONTENT, holdOrderEntity.getSymbol() + "开多", openPrice, followTraderInfoEntity.getNickname()));
+                    } else {
+                        LogRecordUtils.insertMemberAccountFlow(memberEntity.getId(), prePaymentAmount, walletContract.getAvailableBalance().subtract(prePaymentAmount), holdOrderEntity.getSymbol(), "买跌持仓", "买跌:" + holdOrderEntity.getSymbol());
+                        LogRecordUtils.insertFollowerNotice(memberEntity.getId(), NoticeConstant.OPEN_ORDER_TITLE, StrUtil.format(NoticeConstant.OPEN_ORDER_CONTENT, holdOrderEntity.getSymbol() + "开空", openPrice, followTraderInfoEntity.getNickname()));
+                    }
+                }
+            }
+        }
+    }
+
+    public void sendOrderBombMsg(Long id, int type, BigDecimal forceClosingPrice, String symbol, int operateNo) {
+        OrderModel model = null;
+        // 开多
+        if (ContractHoldOrderEntity.OPENING_TYPE_MORE == type) {
+            model = new OrderModel(id, RabbitPriceTypeEnum.CLOSE_MORE_BOMB.getValue(), forceClosingPrice.setScale(8, RoundingMode.HALF_UP).toPlainString(), symbol, operateNo);
+            // 开空
+        } else {
+            model = new OrderModel(id, RabbitPriceTypeEnum.CLOSE_LESS_BOMB.getValue(), forceClosingPrice.setScale(8, RoundingMode.HALF_UP).toPlainString(), symbol, operateNo);
+        }
+        producer.sendPriceOperate(JSONObject.toJSONString(model));
+    }
+}
diff --git a/src/main/java/com/xcong/excoin/utils/LogRecordUtils.java b/src/main/java/com/xcong/excoin/utils/LogRecordUtils.java
index 6bf4189..1722f78 100644
--- a/src/main/java/com/xcong/excoin/utils/LogRecordUtils.java
+++ b/src/main/java/com/xcong/excoin/utils/LogRecordUtils.java
@@ -4,6 +4,8 @@
 import com.xcong.excoin.modules.coin.dao.MemberAccountMoneyChangeDao;
 import com.xcong.excoin.modules.coin.entity.MemberAccountFlowEntity;
 import com.xcong.excoin.modules.coin.entity.MemberAccountMoneyChange;
+import com.xcong.excoin.modules.documentary.dao.FollowFollowerNoticeDao;
+import com.xcong.excoin.modules.documentary.entity.FollowFollowerNoticeEntity;
 
 import java.math.BigDecimal;
 
@@ -15,7 +17,7 @@
  **/
 public class LogRecordUtils {
 
-    public static void insertMemberAccountMoneyChange(Long memberId,String content, BigDecimal amount, String symbol, Integer status, Integer type) {
+    public static void insertMemberAccountMoneyChange(Long memberId, String content, BigDecimal amount, String symbol, Integer status, Integer type) {
         MemberAccountMoneyChange accountRecord = new MemberAccountMoneyChange();
         accountRecord.setContent(content);
         accountRecord.setMemberId(memberId);
@@ -36,4 +38,20 @@
         memberAccountFlowEntity.setRemark(remark);
         SpringContextHolder.getBean(MemberAccountFlowEntityDao.class).insert(memberAccountFlowEntity);
     }
+
+    /**
+     * 插入跟随者消息
+     *
+     * @param memberId 跟随者用户ID
+     * @param title    消息标题
+     * @param content  消息内容
+     */
+    public static void insertFollowerNotice(Long memberId, String title, String content) {
+        FollowFollowerNoticeEntity noticeEntity = new FollowFollowerNoticeEntity();
+        noticeEntity.setMemberId(memberId);
+        noticeEntity.setTitle(title);
+        noticeEntity.setContent(content);
+        SpringContextHolder.getBean(FollowFollowerNoticeDao.class).insert(noticeEntity);
+    }
+
 }
diff --git a/src/main/resources/mapper/documentary/FollowFollowerOrderRelationDao.xml b/src/main/resources/mapper/documentary/FollowFollowerOrderRelationDao.xml
index c546474..f24dcfb 100644
--- a/src/main/resources/mapper/documentary/FollowFollowerOrderRelationDao.xml
+++ b/src/main/resources/mapper/documentary/FollowFollowerOrderRelationDao.xml
@@ -2,4 +2,12 @@
 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="com.xcong.excoin.modules.documentary.dao.FollowFollowerOrderRelationDao">
 
+
+    <select id="selectFollowerHoldingSymbolCnt" resultType="java.lang.Integer">
+        select
+            IFNULL(sum(b.symbol_cnt),0)
+        from follow_follower_order_relation a, contract_hold_order b
+        where a.order_id=b.id and a.order_type=1 and a.trade_member_id=#{tradeMemberId}
+        and a.member_id=#{memberId}
+    </select>
 </mapper>
\ No newline at end of file
diff --git a/src/main/resources/mapper/documentary/FollowFollowerSettingDao.xml b/src/main/resources/mapper/documentary/FollowFollowerSettingDao.xml
index d7a9724..eafdf2e 100644
--- a/src/main/resources/mapper/documentary/FollowFollowerSettingDao.xml
+++ b/src/main/resources/mapper/documentary/FollowFollowerSettingDao.xml
@@ -18,4 +18,11 @@
 			member_id = #{memberId} 
 			and trader_id = #{traderId} 
     </select>
+
+
+	<select id="selectAllFollowerSettingByTradeMemberId" resultType="com.xcong.excoin.modules.documentary.entity.FollowFollowerSettingEntity">
+		select * from follow_follower_setting
+		where trader_member_id=#{memberId}
+	</select>
+
 </mapper>
\ No newline at end of file
diff --git a/src/main/resources/mapper/documentary/FollowTraderInfoDao.xml b/src/main/resources/mapper/documentary/FollowTraderInfoDao.xml
index 268e65b..aee0491 100644
--- a/src/main/resources/mapper/documentary/FollowTraderInfoDao.xml
+++ b/src/main/resources/mapper/documentary/FollowTraderInfoDao.xml
@@ -5,5 +5,9 @@
 	<select id="selectFollowTraderInfoEntityBytreaderId" resultType="com.xcong.excoin.modules.documentary.entity.FollowTraderInfoEntity">
 		select * from follow_trader_info where id = #{traderId}
     </select>
-    
+
+
+	<select id="selectTraderInfoByMemberId" resultType="com.xcong.excoin.modules.documentary.entity.FollowTraderInfoEntity">
+		select * from follow_trader_info where member_id=#{memberId}
+	</select>
 </mapper>
\ No newline at end of file

--
Gitblit v1.9.1