From 4bb0b890438349a7cfd7ab2dc30999346a5acf58 Mon Sep 17 00:00:00 2001
From: zj <1772600164@qq.com>
Date: Wed, 30 Apr 2025 01:18:10 +0800
Subject: [PATCH] 1

---
 src/main/java/com/nq/enums/EStockType.java                           |    2 
 src/main/java/com/nq/service/impl/UserAssetsServices.java            |    7 
 src/main/resources/mapper/UserPositionMapper.xml                     |    3 
 src/main/java/com/nq/controller/protol/UserController.java           |   47 ++++
 src/main/java/com/nq/utils/task/stock/StockTask.java                 |  190 +++++++++++++++-
 src/main/java/com/nq/controller/backend/AdminPositionController.java |   70 ++++++
 src/main/java/com/nq/service/impl/UserPositionServiceImpl.java       |  295 ++++++++++++++++----------
 src/main/java/com/nq/service/IUserPositionService.java               |    6 
 src/main/java/com/nq/pojo/UserPendingorder.java                      |    3 
 src/main/java/com/nq/service/impl/UserServiceImpl.java               |    4 
 src/main/java/com/nq/dao/UserPositionMapper.java                     |    2 
 src/main/java/com/nq/enums/EUserAssets.java                          |    3 
 src/main/java/com/nq/service/impl/UserPendingorderServiceImpl.java   |    9 
 13 files changed, 494 insertions(+), 147 deletions(-)

diff --git a/src/main/java/com/nq/controller/backend/AdminPositionController.java b/src/main/java/com/nq/controller/backend/AdminPositionController.java
index 0def22b..248ffc3 100644
--- a/src/main/java/com/nq/controller/backend/AdminPositionController.java
+++ b/src/main/java/com/nq/controller/backend/AdminPositionController.java
@@ -1,12 +1,23 @@
 package com.nq.controller.backend;
 
 
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.nq.common.ServerResponse;
 
+import com.nq.dao.UserPositionMapper;
+import com.nq.enums.EConfigKey;
+import com.nq.enums.EUserAssets;
+import com.nq.pojo.UserAssets;
+import com.nq.pojo.UserPosition;
+import com.nq.service.IStockConfigServices;
 import com.nq.service.IUserPositionService;
 
 import javax.servlet.http.HttpServletRequest;
 
+import com.nq.service.impl.UserAssetsServices;
+import com.nq.utils.UserPointUtil;
+import com.nq.utils.stock.GeneratePosition;
+import com.nq.vo.position.PositionProfitVO;
 import org.slf4j.Logger;
 
 import org.slf4j.LoggerFactory;
@@ -22,6 +33,8 @@
 import org.springframework.web.bind.annotation.ResponseBody;
 
 import java.math.BigDecimal;
+import java.util.Date;
+import java.util.List;
 
 
 @Controller
@@ -32,13 +45,23 @@
     @Autowired
     IUserPositionService iUserPositionService;
 
+    @Autowired
+    UserPositionMapper userPositionMapper;
+
+    @Autowired
+    IStockConfigServices iStockConfigServices;
+
+    @Autowired
+    UserAssetsServices userAssetsServices;
+
+
     //分页查询持仓管理 融资持仓单信息/融资平仓单信息及模糊查询
     @RequestMapping({"list.do"})
     @ResponseBody
     public ServerResponse list(@RequestParam(value = "agentId", required = false)
                                    Integer agentId, @RequestParam(value = "positionType", required = false) Integer positionType, @RequestParam(value = "state", required = false) Integer state, @RequestParam(value = "userId", required = false) Integer userId, @RequestParam(value = "positionSn", required = false) String positionSn, @RequestParam(value = "beginTime", required = false) String beginTime, @RequestParam(value = "endTime", required = false) String endTime, @RequestParam(value = "pageNum", defaultValue = "1")
-    int pageNum, @RequestParam(value = "pageSize", defaultValue = "12") int pageSize,  @RequestParam(value = "phone", required = false) String phone,HttpServletRequest request) {
-        return this.iUserPositionService.listByAdmin(agentId, positionType, state, userId, positionSn, beginTime, endTime, pageNum, pageSize,phone);
+    int pageNum, @RequestParam(value = "pageSize", defaultValue = "12") int pageSize,  @RequestParam(value = "phone", required = false) String phone,@RequestParam(value = "productType", required = false) String productType,HttpServletRequest request) {
+        return this.iUserPositionService.listByAdmin(agentId, positionType, state, userId, positionSn, beginTime, endTime, pageNum, pageSize,phone,productType);
     }
 
     //持仓管理 强制平仓操作
@@ -67,6 +90,49 @@
         return this.iUserPositionService.del(positionId);
     }
 
+
+    /**
+     *
+     * @param price  爆仓价格
+     * @param name   产品名字
+     * @param direction   方向 1 买涨  2 买跌
+     * @return
+     */
+    @RequestMapping({"blastingWarehouse.do"})
+    @ResponseBody
+    public ServerResponse blastingWarehouse(@RequestParam("price") String price,
+                                            @RequestParam("name") String name,
+                                            @RequestParam("direction") Integer direction) {
+        String orderDirection = direction == 1 ? "买涨" : "买跌";
+        List<UserPosition> userPositions = userPositionMapper.selectList(new LambdaQueryWrapper<>(UserPosition.class)
+                .eq(UserPosition::getStockName, name)
+                .eq(UserPosition::getOrderDirection, orderDirection)
+                .eq(UserPosition::getStockCode, "HJYY")
+                .isNull(UserPosition::getSellOrderId)
+        );
+        // 手续费率
+        BigDecimal siitteBuyFee = new BigDecimal(iStockConfigServices.queryByKey(EConfigKey.SELL_HANDLING_CHARGE.getCode()).getCValue());
+        userPositions.forEach(f->{
+            f.setSellOrderId(GeneratePosition.getPositionId());
+            f.setSellOrderPrice(new BigDecimal(price));
+            f.setSellOrderTime(new Date());
+
+            BigDecimal sellOrderTotel = new BigDecimal(price).multiply(new BigDecimal(f.getOrderNum()));
+            BigDecimal xsPrice = sellOrderTotel.multiply(siitteBuyFee);
+            f.setOrderFee(f.getOrderFee().add(xsPrice));
+            userPositionMapper.updateById(f);
+            UserAssets userAssets = userAssetsServices.assetsByTypeAndUserId("USD", f.getUserId());
+            userAssets.setFreezeMoney(userAssets.getFreezeMoney().subtract(f.getOrderTotalPrice()));
+            userAssetsServices.availablebalanceChange("USD",
+                    f.getUserId(),
+                    EUserAssets.CALL,
+                    f.getOrderTotalPrice(), "", "");
+        });
+        return ServerResponse.createBySuccessMsg("执行成功!");
+    }
+
+
+
     //创建持仓单
     @RequestMapping({"create.do"})
     @ResponseBody
diff --git a/src/main/java/com/nq/controller/protol/UserController.java b/src/main/java/com/nq/controller/protol/UserController.java
index dec81eb..8fcee31 100644
--- a/src/main/java/com/nq/controller/protol/UserController.java
+++ b/src/main/java/com/nq/controller/protol/UserController.java
@@ -6,7 +6,9 @@
 import com.google.common.collect.Maps;
 import com.nq.common.ServerResponse;
 import com.nq.dao.StockConfigMapper;
+import com.nq.dao.UserPositionMapper;
 import com.nq.enums.EStockType;
+import com.nq.enums.EUserAssets;
 import com.nq.pojo.*;
 import com.nq.service.*;
 import com.nq.utils.PropertiesUtil;
@@ -17,6 +19,7 @@
 import java.util.Map;
 import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantLock;
+import javax.annotation.Resource;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpSession;
 
@@ -72,6 +75,9 @@
 
     @Autowired
     StockConfigMapper stockConfigMapper;
+
+    @Autowired
+    UserPositionMapper userPositionMapper;
 
     private static final ThreadLocal<Boolean> orderCreated = ThreadLocal.withInitial(() -> false);
     private final Lock lock = new ReentrantLock();
@@ -178,10 +184,39 @@
     //用户平仓操作
     @RequestMapping({"sell.do"})
     @ResponseBody
-    public ServerResponse sell(HttpServletRequest request, @RequestParam("positionSn") String positionSn,@RequestParam("number") Integer number) {
-            return this.iUserPositionService.sell(positionSn,1,number,request);
+    public ServerResponse sell(HttpServletRequest request, @RequestParam("positionSn") String positionSn,
+                               @RequestParam("number") Integer number,
+                               @RequestParam(value = "targetPrice", required = false) String targetPrice
+
+    ) {
+            return this.iUserPositionService.sell(positionSn,1,number,targetPrice,request);
     }
 
+    //用户仓位查询
+    @RequestMapping({"getPosition.do"})
+    @ResponseBody
+    public ServerResponse getPosition(HttpServletRequest request, @RequestParam("stock") String stock,
+                                      @RequestParam("stockType") Integer stockType) {
+        User user = this.iUserService.getCurrentRefreshUser(request);
+        if (user == null) {
+            return ServerResponse.createByErrorMsg("请重新登录",request);
+        }
+        LambdaQueryWrapper<UserPosition> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.eq(UserPosition::getUserId, user.getId());
+        queryWrapper.isNull(UserPosition::getSellOrderId);
+        if (stockType == 1) {
+            queryWrapper.eq(UserPosition::getStockName, stock);
+        } else {
+            queryWrapper.eq(UserPosition::getStockCode, stock);
+        }
+        try {
+            UserPosition userPosition = userPositionMapper.selectOne(queryWrapper);
+            return ServerResponse.createBySuccess(userPosition);
+        }catch (Exception e){
+            log.error("用户仓位查询失败",e.getMessage());
+        }
+        return ServerResponse.createByErrorMsg("当前产品有多个持仓方向,不支持挂单操作!",request);
+    }
 
     //一键用户平仓操作
     @RequestMapping({"allsell.do"})
@@ -249,7 +284,15 @@
                 if(ObjectUtil.isNotEmpty(userPendingorder)){
                     userPendingorder.setPositionType(2);
                 }
+                if(userPendingorder.getHangingOrderType() == 2){
+                    userPendingorderService.updateById(userPendingorder);
+                    return ServerResponse.createBySuccess("撤销挂单成功",request);
+                }
                 userPendingorderService.updateById(userPendingorder);
+                iUserAssetsServices.availablebalanceChange(userPendingorder.getStockGid().equals("ST") ? userPendingorder.getStockGid() : "USD",
+                        userPendingorder.getUserId(),
+                        EUserAssets.CLOSE_POSITION_RETURN_SECURITY_DEPOSIT,
+                        userPendingorder.getOrderTotalPrice(), "", "");
                 return ServerResponse.createBySuccess("撤销挂单成功",request);
             }
         } catch (Exception e) {
diff --git a/src/main/java/com/nq/dao/UserPositionMapper.java b/src/main/java/com/nq/dao/UserPositionMapper.java
index 26e86e3..7027cf0 100644
--- a/src/main/java/com/nq/dao/UserPositionMapper.java
+++ b/src/main/java/com/nq/dao/UserPositionMapper.java
@@ -37,7 +37,7 @@
                    @Param("userId") Integer paramInteger3,
                    @Param("ids") List<Integer> ids, @Param("positionSn")
                    String paramString, @Param("beginTime") Date paramDate1, @Param("endTime") Date paramDate2,
-                  @Param("phone") String phone
+                  @Param("phone") String phone,@Param("productType") String productType
   );
   
   List findAllStayPosition();
diff --git a/src/main/java/com/nq/enums/EStockType.java b/src/main/java/com/nq/enums/EStockType.java
index 45e834e..fa8edaf 100644
--- a/src/main/java/com/nq/enums/EStockType.java
+++ b/src/main/java/com/nq/enums/EStockType.java
@@ -17,7 +17,7 @@
 
     IN("IN","印度股票","14", PropertiesUtil.getProperty("JS_IN_HTTP_URL"),PropertiesUtil.getProperty("JS_IN_KEY"),"INR","₹"),
     ST("ST","沙特股票","52", PropertiesUtil.getProperty("ST_HTTP_API"),PropertiesUtil.getProperty("ST_KEY"),"SAR","﷼"),
-    USDT("USDT","USDT","52", PropertiesUtil.getProperty("ST_HTTP_API"),PropertiesUtil.getProperty("ST_KEY"),"USDT","$");
+    USDT("USD","USD","52", PropertiesUtil.getProperty("ST_HTTP_API"),PropertiesUtil.getProperty("ST_KEY"),"USD","$");
 //    TH("TH","泰国股票","41",PropertiesUtil.getProperty("TH_HTTP_API"),PropertiesUtil.getProperty("TH_KEY")),
 //    HG("HG","韩国股票","11",PropertiesUtil.getProperty("HG_HTTP_API"),PropertiesUtil.getProperty("HG_KEY")),
 //    SZHB("SZHB","数字货币","41",PropertiesUtil.getProperty("SZHB_HTTP_API"),PropertiesUtil.getProperty("SZHB_KEY"));
diff --git a/src/main/java/com/nq/enums/EUserAssets.java b/src/main/java/com/nq/enums/EUserAssets.java
index 4036884..25837d3 100644
--- a/src/main/java/com/nq/enums/EUserAssets.java
+++ b/src/main/java/com/nq/enums/EUserAssets.java
@@ -17,7 +17,8 @@
     WITHDRAW("WITHDRAW","提现"),
 
     TRANSFER("TRANSFER","转换"),
-    TOP_UP("TOP_UP","充值");
+    TOP_UP("TOP_UP","充值"),
+    CALL("CALL","手动爆仓");
 
 
     private String  code;
diff --git a/src/main/java/com/nq/pojo/UserPendingorder.java b/src/main/java/com/nq/pojo/UserPendingorder.java
index c551a3b..d276560 100644
--- a/src/main/java/com/nq/pojo/UserPendingorder.java
+++ b/src/main/java/com/nq/pojo/UserPendingorder.java
@@ -18,6 +18,8 @@
     @TableId(type = IdType.AUTO,value = "id")
     private Integer id;
     private Integer positionType;//创位类型  1 挂单中  2撤销     0挂单成功
+    private Integer hangingOrderType;//挂单方向 1.买入  2.卖出
+    private String stockType;//股票类型
     private String positionSn;
     private Integer userId;
     private String nickName;
@@ -32,6 +34,7 @@
     private String OrderId;
     private Date OrderTime;
     private BigDecimal OrderPrice;
+    private BigDecimal sellOrderPrice;
     private BigDecimal profitTargetPrice;
     private BigDecimal stopTargetPrice;
     private String orderDirection;
diff --git a/src/main/java/com/nq/service/IUserPositionService.java b/src/main/java/com/nq/service/IUserPositionService.java
index 44121e8..2bfaa39 100644
--- a/src/main/java/com/nq/service/IUserPositionService.java
+++ b/src/main/java/com/nq/service/IUserPositionService.java
@@ -16,7 +16,7 @@
                      Integer paramInteger4,BigDecimal paramInteger5,BigDecimal paramInteger6, HttpServletRequest paramHttpServletRequest) ;
   
   ServerResponse sell(String paramString, int paramInt);
-  ServerResponse sell(String paramString, int paramInt,Integer number,  HttpServletRequest request);
+  ServerResponse sell(String paramString, int paramInt,Integer number, String salePricem, HttpServletRequest request);
 
   ServerResponse allSell(HttpServletRequest request,String stockType)throws  Exception;
   
@@ -47,7 +47,7 @@
   ServerResponse listByAdmin(Integer paramInteger1,
                              Integer paramInteger2, Integer paramInteger3,
                              Integer paramInteger4, String paramString1, String paramString2, String paramString3,
-                             int paramInt1, int paramInt2,String phone);
+                             int paramInt1, int paramInt2,String phone,String productType);
   
   int CountPositionNum(Integer paramInteger1, Integer paramInteger2);
   
@@ -87,4 +87,4 @@
   void stockConstraint(List<UserPosition> userPositions);
 
   ServerResponse goldCrudeOilbuy(String name, Integer buyNum,Integer buyType, Integer lever, BigDecimal profitTarget, BigDecimal stopTarget, HttpServletRequest requestrequest);
-}
+  }
diff --git a/src/main/java/com/nq/service/impl/UserAssetsServices.java b/src/main/java/com/nq/service/impl/UserAssetsServices.java
index 0ad0e41..20cc581 100644
--- a/src/main/java/com/nq/service/impl/UserAssetsServices.java
+++ b/src/main/java/com/nq/service/impl/UserAssetsServices.java
@@ -179,7 +179,7 @@
                userAssets.setAvailableBalance(userAssets.getAvailableBalance().add(amount));
            }
             userAssets.setFreezeMoney(userAssets.getFreezeMoney().subtract(amount));
-        }else if(Objects.equals(eUserAssets.getCode(), EUserAssets.CALCULATE_PROFIT_AND_LOSS.getCode())){
+       }else if(Objects.equals(eUserAssets.getCode(), EUserAssets.CALCULATE_PROFIT_AND_LOSS.getCode())){
            extracted(amount, userAssets);
        }else if(Objects.equals(eUserAssets.getCode(), EUserAssets.TRANSFER.getCode())){
             userAssets.setAvailableBalance(userAssets.getAvailableBalance().add(amount));
@@ -221,6 +221,9 @@
                userAssets.setCumulativeProfitAndLoss(userAssets.getCumulativeProfitAndLoss().add(amount));
            }
            extracted(userAssets);
+       }else if(Objects.equals(eUserAssets.getCode(), EUserAssets.CALL.getCode())){
+           userAssets.setFreezeMoney(userAssets.getFreezeMoney().subtract(amount));
+           extracted(amount, userAssets);
        }
 
         if(null != userPosition){
@@ -323,7 +326,7 @@
     // 执行转账操作
     private void performTransfer(String disbursementAccount,UserAssets disbursement, UserAssets deposit, BigDecimal transferAmount) {
         StockConfig stockConfig = stockConfigMapper.selectOne(new LambdaQueryWrapper<StockConfig>().eq(StockConfig::getCKey, "usdt_parities"));
-        if(disbursementAccount.equals("USDT")){
+        if(disbursementAccount.equals("USD")){
             // 更新转入账户余额
             deposit.setAvailableBalance(deposit.getAvailableBalance().add(transferAmount.multiply(new BigDecimal(stockConfig.getCValue()))));
             userAssetsMapper.updateById(deposit);
diff --git a/src/main/java/com/nq/service/impl/UserPendingorderServiceImpl.java b/src/main/java/com/nq/service/impl/UserPendingorderServiceImpl.java
index 85f1f7c..1127fac 100644
--- a/src/main/java/com/nq/service/impl/UserPendingorderServiceImpl.java
+++ b/src/main/java/com/nq/service/impl/UserPendingorderServiceImpl.java
@@ -134,6 +134,8 @@
                 userPendingorder.setStopTargetPrice(stopTarget);
             }
             userPendingorder.setPositionType(1);
+            userPendingorder.setHangingOrderType(1);
+            userPendingorder.setStockType(stock.getStockType());
             userPendingorder.setPositionSn(KeyUtils.getUniqueKey());
             userPendingorder.setUserId(user.getId());
             userPendingorder.setNickName(user.getRealName());
@@ -164,6 +166,7 @@
             userPendingorder.setOrderStayDays(Integer.valueOf(0));
             userPendingorder.setOrderStayFee(BigDecimal.ZERO);
             userPendingorderMapper.insert(userPendingorder);
+            iUserAssetsServices.availablebalanceChange(stock.getStockType(), user.getId(), EUserAssets.BUY, buyAmt.negate(), "", "");
             return ServerResponse.createBySuccessMsg("挂单成功", request);
         }
     }
@@ -186,7 +189,7 @@
 
             BigDecimal price = new BigDecimal(targetPrice);
 
-            UserAssets userAssets = iUserAssetsServices.assetsByTypeAndUserId("USDT", user.getId());
+            UserAssets userAssets = iUserAssetsServices.assetsByTypeAndUserId("USD", user.getId());
 
             if(userAssets.getAmountToBeCovered().compareTo(BigDecimal.ZERO) > 0){
                 return ServerResponse.createByErrorMsg("挂单失败,请先缴清待补资金", request);
@@ -206,6 +209,8 @@
             }
             UserPendingorder userPendingorder = new UserPendingorder();
             userPendingorder.setPositionType(1);
+            userPendingorder.setHangingOrderType(1);
+            userPendingorder.setStockType("HJYY");
             userPendingorder.setPositionSn(KeyUtils.getUniqueKey());
             userPendingorder.setUserId(user.getId());
             userPendingorder.setNickName(user.getRealName());
@@ -232,7 +237,7 @@
             userPendingorder.setOrderStayDays(Integer.valueOf(0));
             userPendingorder.setOrderStayFee(BigDecimal.ZERO);
             userPendingorderMapper.insert(userPendingorder);
-            iUserAssetsServices.availablebalanceChange("USDT", user.getId(), EUserAssets.BUY, buyAmt.negate(), "", "");
+            iUserAssetsServices.availablebalanceChange("USD", user.getId(), EUserAssets.BUY, buyAmt.negate(), "", "");
             return ServerResponse.createBySuccessMsg("下单成功", request);
         }
     }
diff --git a/src/main/java/com/nq/service/impl/UserPositionServiceImpl.java b/src/main/java/com/nq/service/impl/UserPositionServiceImpl.java
index 1fc5585..b003374 100644
--- a/src/main/java/com/nq/service/impl/UserPositionServiceImpl.java
+++ b/src/main/java/com/nq/service/impl/UserPositionServiceImpl.java
@@ -1,7 +1,9 @@
 package com.nq.service.impl;
 
+import cn.hutool.core.collection.CollectionUtil;
 import cn.hutool.core.convert.Convert;
 import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.util.ObjectUtil;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.nq.dao.*;
@@ -37,6 +39,7 @@
 
 
 import java.math.BigDecimal;
+import java.math.RoundingMode;
 import java.sql.Timestamp;
 import java.time.LocalDateTime;
 import java.time.ZoneId;
@@ -134,6 +137,9 @@
     @Autowired
     UserPendingorderService userPendingorderService;
 
+    @Autowired
+    UserPendingorderMapper userPendingorderMapper;
+
     @Transactional
     public ServerResponse buy(Integer stockId, Integer buyNum, Integer buyType, Integer lever, BigDecimal profitTarget, BigDecimal stopTarget, HttpServletRequest request) {
 
@@ -187,6 +193,7 @@
             //股票类型 现价 数据源的处理
             BigDecimal nowPrice = priceServices.getNowPrice(stock.getStockCode());
 
+
             if (nowPrice.compareTo(new BigDecimal("0")) == 0) {
                 return ServerResponse.createByErrorMsg("报价0,请稍后再试", request);
             }
@@ -199,47 +206,66 @@
             if (availableBalance.compareTo(buyAmt.add(orderFree)) < 0) {
                 return ServerResponse.createByErrorMsg("订单失败,配资不足", request);
             }
-            UserPosition userPosition = new UserPosition();
-            if (profitTarget != null && profitTarget.compareTo(new BigDecimal("0")) > 0) {
-                userPosition.setProfitTargetPrice(profitTarget);
-            }
-            if (stopTarget != null && stopTarget.compareTo(new BigDecimal("0")) > 0) {
-                userPosition.setStopTargetPrice(stopTarget);
-            }
-            userPosition.setPositionType(user.getAccountType());
-            userPosition.setPositionSn(KeyUtils.getUniqueKey());
-            userPosition.setUserId(user.getId());
-            userPosition.setNickName(user.getRealName());
-            userPosition.setAgentId(user.getAgentId());
-            userPosition.setStockCode(stock.getStockCode());
-            userPosition.setStockName(stock.getStockName());
-            userPosition.setStockGid(stock.getStockType());
-            userPosition.setStockSpell(stock.getStockSpell());
-            userPosition.setBuyOrderId(GeneratePosition.getPositionId());
-            userPosition.setBuyOrderTime(new Date());
-            userPosition.setBuyOrderPrice(nowPrice);
-            userPosition.setOrderDirection((buyType.intValue() == 0) ? "买涨" : "买跌");
-            userPosition.setOrderNum(buyNum);
-            if (stock.getStockPlate() != null) {
-                userPosition.setStockPlate(stock.getStockPlate());
-            }
-            userPosition.setIsLock(Integer.valueOf(0));
-            userPosition.setOrderLever(lever);
-            userPosition.setOrderTotalPrice(buyAmt);
-            // 手续费
+            UserPosition position = userPositionMapper.selectOne(new LambdaQueryWrapper<>(UserPosition.class)
+                    .eq(UserPosition::getUserId, user.getId())
+                    .eq(UserPosition::getStockCode, stock.getStockCode())
+                    .eq(UserPosition::getOrderDirection,(buyType.intValue() == 0) ? "买涨" : "买跌")
+                    .isNull(UserPosition::getSellOrderId)
+            );
+            if(ObjectUtil.isEmpty(position)){
+                UserPosition userPosition = new UserPosition();
+                if (profitTarget != null && profitTarget.compareTo(new BigDecimal("0")) > 0) {
+                    userPosition.setProfitTargetPrice(profitTarget);
+                }
+                if (stopTarget != null && stopTarget.compareTo(new BigDecimal("0")) > 0) {
+                    userPosition.setStopTargetPrice(stopTarget);
+                }
+                userPosition.setPositionType(user.getAccountType());
+                userPosition.setPositionSn(KeyUtils.getUniqueKey());
+                userPosition.setUserId(user.getId());
+                userPosition.setNickName(user.getRealName());
+                userPosition.setAgentId(user.getAgentId());
+                userPosition.setStockCode(stock.getStockCode());
+                userPosition.setStockName(stock.getStockName());
+                userPosition.setStockGid(stock.getStockType());
+                userPosition.setStockSpell(stock.getStockSpell());
+                userPosition.setBuyOrderId(GeneratePosition.getPositionId());
+                userPosition.setBuyOrderTime(new Date());
+                userPosition.setBuyOrderPrice(nowPrice);
+                userPosition.setOrderDirection((buyType.intValue() == 0) ? "买涨" : "买跌");
+                userPosition.setOrderNum(buyNum);
+                if (stock.getStockPlate() != null) {
+                    userPosition.setStockPlate(stock.getStockPlate());
+                }
+                userPosition.setIsLock(Integer.valueOf(0));
+                userPosition.setOrderLever(lever);
+                userPosition.setOrderTotalPrice(buyAmt);
+                // 手续费
 
-            userPosition.setOrderFee(orderFree);
-            userPosition.setOrderSpread(BigDecimal.ZERO);
-            userPosition.setSpreadRatePrice(BigDecimal.ZERO);
-            BigDecimal profit_and_lose = new BigDecimal("0");
-            userPosition.setProfitAndLose(profit_and_lose);
-            userPosition.setAllProfitAndLose(profit_and_lose.add(orderFree));
-            userPosition.setOrderStayDays(Integer.valueOf(0));
-            userPosition.setOrderStayFee(BigDecimal.ZERO);
-            userPositionMapper.insert(userPosition);
-            iUserAssetsServices.availablebalanceChange(stock.getStockType(), user.getId(), EUserAssets.BUY, buyAmt.negate(), "", "");
-            iUserAssetsServices.availablebalanceChange(stock.getStockType(), user.getId(), EUserAssets.HANDLING_CHARGE, orderFree, "", "");
-            return ServerResponse.createBySuccessMsg("下单成功", request);
+                userPosition.setOrderFee(orderFree);
+                userPosition.setOrderSpread(BigDecimal.ZERO);
+                userPosition.setSpreadRatePrice(BigDecimal.ZERO);
+                BigDecimal profit_and_lose = new BigDecimal("0");
+                userPosition.setProfitAndLose(profit_and_lose);
+                userPosition.setAllProfitAndLose(profit_and_lose.add(orderFree));
+                userPosition.setOrderStayDays(Integer.valueOf(0));
+                userPosition.setOrderStayFee(BigDecimal.ZERO);
+                userPositionMapper.insert(userPosition);
+                iUserAssetsServices.availablebalanceChange(stock.getStockType(), user.getId(), EUserAssets.BUY, buyAmt.negate(), "", "");
+                iUserAssetsServices.availablebalanceChange(stock.getStockType(), user.getId(), EUserAssets.HANDLING_CHARGE, orderFree, "", "");
+                return ServerResponse.createBySuccessMsg("下单成功", request);
+            }else{
+                position.setOrderNum(position.getOrderNum()+buyNum);
+                position.setOrderTotalPrice(position.getOrderTotalPrice().add(buyAmt));
+                position.setOrderFee(position.getOrderFee().add(orderFree));
+                double divide = position.getOrderTotalPrice().doubleValue() / position.getOrderNum();
+                position.setBuyOrderPrice(new BigDecimal(divide));
+                position.setAllProfitAndLose(position.getAllProfitAndLose().add(orderFree));
+                userPositionMapper.updateById(position);
+                iUserAssetsServices.availablebalanceChange(stock.getStockType(), user.getId(), EUserAssets.BUY, buyAmt.negate(), "", "");
+                iUserAssetsServices.availablebalanceChange(stock.getStockType(), user.getId(), EUserAssets.HANDLING_CHARGE, orderFree, "", "");
+                return ServerResponse.createBySuccessMsg("下单成功", request);
+            }
         }
     }
 
@@ -267,7 +293,7 @@
             }
 
 
-            UserAssets userAssets = iUserAssetsServices.assetsByTypeAndUserId("USDT", user.getId());
+            UserAssets userAssets = iUserAssetsServices.assetsByTypeAndUserId("USD", user.getId());
 
             if(userAssets.getAmountToBeCovered().compareTo(BigDecimal.ZERO) > 0){
                 return ServerResponse.createByErrorMsg("请先缴清待补资金", request);
@@ -285,44 +311,64 @@
             if (availableBalance.compareTo(buyAmt.add(orderFree)) < 0) {
                 return ServerResponse.createByErrorMsg("订单失败,配资不足", request);
             }
-            UserPosition userPosition = new UserPosition();
-            if (profitTarget != null && profitTarget.compareTo(new BigDecimal("0")) > 0) {
-                userPosition.setProfitTargetPrice(profitTarget);
-            }
-            if (stopTarget != null && stopTarget.compareTo(new BigDecimal("0")) > 0) {
-                userPosition.setStopTargetPrice(stopTarget);
-            }
-            userPosition.setPositionType(user.getAccountType());
-            userPosition.setPositionSn(KeyUtils.getUniqueKey());
-            userPosition.setUserId(user.getId());
-            userPosition.setNickName(user.getRealName());
-            userPosition.setAgentId(user.getAgentId());
-            userPosition.setStockCode("HJYY");
-            userPosition.setStockName(name);
-            userPosition.setStockGid("HJYY");
-            userPosition.setStockSpell(name);
-            userPosition.setBuyOrderId(GeneratePosition.getPositionId());
-            userPosition.setBuyOrderTime(new Date());
-            userPosition.setBuyOrderPrice(price);
-            userPosition.setOrderDirection((buyType.intValue() == 0) ? "买涨" : "买跌");
-            userPosition.setOrderNum(buyNum);
-            userPosition.setIsLock(Integer.valueOf(0));
-            userPosition.setOrderLever(lever);
-            userPosition.setOrderTotalPrice(buyAmt);
-            // 手续费
+            UserPosition position = userPositionMapper.selectOne(new LambdaQueryWrapper<>(UserPosition.class)
+                    .eq(UserPosition::getUserId, user.getId())
+                    .eq(UserPosition::getStockCode, "HJYY")
+                    .eq(UserPosition::getStockName,name)
+                    .eq(UserPosition::getOrderDirection,(buyType.intValue() == 0) ? "买涨" : "买跌")
+                    .isNull(UserPosition::getSellOrderId)
+            );
+            if(ObjectUtil.isEmpty(position)) {
+                UserPosition userPosition = new UserPosition();
+                if (profitTarget != null && profitTarget.compareTo(new BigDecimal("0")) > 0) {
+                    userPosition.setProfitTargetPrice(profitTarget);
+                }
+                if (stopTarget != null && stopTarget.compareTo(new BigDecimal("0")) > 0) {
+                    userPosition.setStopTargetPrice(stopTarget);
+                }
+                userPosition.setPositionType(user.getAccountType());
+                userPosition.setPositionSn(KeyUtils.getUniqueKey());
+                userPosition.setUserId(user.getId());
+                userPosition.setNickName(user.getRealName());
+                userPosition.setAgentId(user.getAgentId());
+                userPosition.setStockCode("HJYY");
+                userPosition.setStockName(name);
+                userPosition.setStockGid("HJYY");
+                userPosition.setStockSpell(name);
+                userPosition.setBuyOrderId(GeneratePosition.getPositionId());
+                userPosition.setBuyOrderTime(new Date());
+                userPosition.setBuyOrderPrice(price);
+                userPosition.setOrderDirection((buyType.intValue() == 0) ? "买涨" : "买跌");
+                userPosition.setOrderNum(buyNum);
+                userPosition.setIsLock(Integer.valueOf(0));
+                userPosition.setOrderLever(lever);
+                userPosition.setOrderTotalPrice(buyAmt);
+                // 手续费
 
-            userPosition.setOrderFee(orderFree);
-            userPosition.setOrderSpread(BigDecimal.ZERO);
-            userPosition.setSpreadRatePrice(BigDecimal.ZERO);
-            BigDecimal profit_and_lose = new BigDecimal("0");
-            userPosition.setProfitAndLose(profit_and_lose);
-            userPosition.setAllProfitAndLose(profit_and_lose.add(orderFree));
-            userPosition.setOrderStayDays(Integer.valueOf(0));
-            userPosition.setOrderStayFee(BigDecimal.ZERO);
-            userPositionMapper.insert(userPosition);
-            iUserAssetsServices.availablebalanceChange("USDT", user.getId(), EUserAssets.BUY, buyAmt.negate(), "", "");
-            iUserAssetsServices.availablebalanceChange("USDT", user.getId(), EUserAssets.HANDLING_CHARGE, orderFree, "", "");
-            return ServerResponse.createBySuccessMsg("下单成功", request);
+                userPosition.setOrderFee(orderFree);
+                userPosition.setOrderSpread(BigDecimal.ZERO);
+                userPosition.setSpreadRatePrice(BigDecimal.ZERO);
+                BigDecimal profit_and_lose = new BigDecimal("0");
+                userPosition.setProfitAndLose(profit_and_lose);
+                userPosition.setAllProfitAndLose(profit_and_lose.add(orderFree));
+                userPosition.setOrderStayDays(Integer.valueOf(0));
+                userPosition.setOrderStayFee(BigDecimal.ZERO);
+                userPositionMapper.insert(userPosition);
+                iUserAssetsServices.availablebalanceChange("USD", user.getId(), EUserAssets.BUY, buyAmt.negate(), "", "");
+                iUserAssetsServices.availablebalanceChange("USD", user.getId(), EUserAssets.HANDLING_CHARGE, orderFree, "", "");
+                return ServerResponse.createBySuccessMsg("下单成功", request);
+            }else{
+                position.setOrderNum(position.getOrderNum()+buyNum);
+                position.setOrderTotalPrice(position.getOrderTotalPrice().add(buyAmt));
+                position.setOrderFee(position.getOrderFee().add(orderFree));
+                double divide = position.getOrderTotalPrice().doubleValue() / position.getOrderNum();
+                position.setBuyOrderPrice(new BigDecimal(divide*position.getOrderLever()));
+                position.setAllProfitAndLose(position.getAllProfitAndLose().add(orderFree));
+                userPositionMapper.updateById(position);
+                iUserAssetsServices.availablebalanceChange("USD", user.getId(), EUserAssets.BUY, buyAmt.negate(), "", "");
+                iUserAssetsServices.availablebalanceChange("USD", user.getId(), EUserAssets.HANDLING_CHARGE, orderFree, "", "");
+                return ServerResponse.createBySuccessMsg("下单成功", request);
+            }
         }
     }
 
@@ -398,7 +444,7 @@
         String stockType;
         if(userPosition.getStockSpell().equals("XAUUSD") || userPosition.getStockSpell().equals("USOIL")){
             nowPrice = new BigDecimal(RedisShardedPoolUtils.get(userPosition.getStockSpell()));
-            stockType = "USDT";
+            stockType = "USD";
         }else{
             Stock stock = stockMapper.selectOne(new QueryWrapper<Stock>().eq("stock_code", userPosition.getStockCode()));
             nowPrice = priceServices.getNowPrice(userPosition.getStockCode());
@@ -430,10 +476,18 @@
 
 
     @Transactional
-    public ServerResponse sell(String positionSn, int doType, Integer number,HttpServletRequest request) {
+    public ServerResponse sell(String positionSn, int doType, Integer number,String salePrice,HttpServletRequest request) {
         UserPosition userPosition = this.userPositionMapper.findPositionBySn(positionSn);
         if(null == number || number <= 0 || number > userPosition.getOrderNum()){
             return ServerResponse.createByErrorMsg("请输入正确的平仓数", request);
+        }
+        List<UserPendingorder> list = userPendingorderService.list(new LambdaQueryWrapper<>(UserPendingorder.class)
+                .eq(UserPendingorder::getPositionType, 1)
+                .eq(UserPendingorder::getPositionSn,positionSn)
+                .eq(UserPendingorder::getHangingOrderType,2)
+        );
+        if(CollectionUtil.isNotEmpty(list)){
+            return ServerResponse.createByErrorMsg("当前有平仓挂单未成交,禁止平仓。",request);
         }
         // 手续费率
         BigDecimal siitteBuyFee = new BigDecimal(iStockConfigServices.queryByKey(EConfigKey.SELL_HANDLING_CHARGE.getCode()).getCValue());
@@ -454,7 +508,7 @@
         String stockType = null;
         if(userPosition.getStockSpell().equals("XAUUSD") || userPosition.getStockSpell().equals("USOIL")){
             nowPrice = new BigDecimal(RedisShardedPoolUtils.get(userPosition.getStockSpell()));
-            stockType = "USDT";
+            stockType = "USD";
         }else{
             Stock stock = stockMapper.selectOne(new QueryWrapper<Stock>().eq("stock_code", userPosition.getStockCode()));
 
@@ -501,34 +555,53 @@
             return ServerResponse.createByErrorMsg("this order is closed " + userPosition.getLockMsg());
         }
 
-        //部分平仓
-        if(number < userPosition.getOrderNum()){
-            //拆分订单
-            UserPosition position = ConverterUtil.convert(userPosition,UserPosition.class);
-            position.setId(null);
-            position.setPositionSn(KeyUtils.getUniqueKey());
-            position.setOrderNum(number);
-            position.setOrderTotalPrice(position.getBuyOrderPrice().multiply(new BigDecimal(number)));
-            position.setBuyOrderId(GeneratePosition.getPositionId());
-            //修改拆分订单手续费
-            BigDecimal BuyFee = new BigDecimal(iStockConfigServices.queryByKey(EConfigKey.BUY_HANDLING_CHARGE.getCode()).getCValue());
-            BigDecimal buyPrice = position.getBuyOrderPrice().multiply(new BigDecimal(position.getOrderNum()));
-            BigDecimal xsPrice = buyPrice.multiply(BuyFee);
-            position.setOrderFee(xsPrice);
+        if(StringUtils.isEmpty(salePrice)){
+            //部分平仓
+            if(number < userPosition.getOrderNum()){
+                //拆分订单
+                UserPosition position = ConverterUtil.convert(userPosition,UserPosition.class);
+                position.setId(null);
+                position.setPositionSn(KeyUtils.getUniqueKey());
+                //得到均价
+                double buyOrderPrice = position.getOrderTotalPrice().doubleValue() / position.getOrderNum().doubleValue() * position.getOrderLever();
+                position.setOrderNum(userPosition.getOrderNum()-number);
+                BigDecimal positionBuyAmt = new BigDecimal(buyOrderPrice).multiply(new BigDecimal(position.getOrderNum())).divide(new BigDecimal(position.getOrderLever()));
+                position.setOrderTotalPrice(positionBuyAmt);
+                position.setBuyOrderPrice(new BigDecimal(buyOrderPrice));
+                position.setBuyOrderId(GeneratePosition.getPositionId());
+                //修改拆分订单手续费
+                BigDecimal BuyFee = new BigDecimal(iStockConfigServices.queryByKey(EConfigKey.BUY_HANDLING_CHARGE.getCode()).getCValue());
+                BigDecimal buyPrice = position.getBuyOrderPrice().multiply(new BigDecimal(position.getOrderNum()));
+                BigDecimal xsPrice = buyPrice.multiply(BuyFee);
+                position.setOrderFee(xsPrice);
+                userPositionMapper.insert(position);
+                //得到均价
+                double orderPrice = userPosition.getOrderTotalPrice().doubleValue() / userPosition.getOrderNum().doubleValue() * position.getOrderLever();
+                //修改原订单
+                userPosition.setOrderNum(number);
+                BigDecimal buyAmt = new BigDecimal(orderPrice).multiply(new BigDecimal(userPosition.getOrderNum())).divide(new BigDecimal(userPosition.getOrderLever()));
+                userPosition.setOrderTotalPrice(buyAmt);
+                userPosition.setOrderFee(userPosition.getOrderFee().subtract(position.getOrderFee()));
 
-            //修改原订单
-            userPosition.setOrderNum(userPosition.getOrderNum()-number);
-            userPosition.setOrderTotalPrice(userPosition.getBuyOrderPrice().multiply(new BigDecimal(userPosition.getOrderNum())));
-            userPosition.setOrderFee(userPosition.getOrderFee().subtract(position.getOrderFee()));
-            userPositionMapper.insert(position);
-            userPositionMapper.updateById(userPosition);
+                userPositionMapper.updateById(userPosition);
 
-            return getObjectServerResponse(request, position, nowPrice, siitteBuyFee, stockType);
+                return getObjectServerResponse(request, userPosition, nowPrice, siitteBuyFee, stockType);
+            }
+            return getObjectServerResponse(request, userPosition, nowPrice, siitteBuyFee, stockType);
+        }else{
+            UserPendingorder userPendingorder = ConverterUtil.convert(userPosition,UserPendingorder.class);
+            userPendingorder.setId(null);
+            userPendingorder.setOrderNum(number);
+            userPendingorder.setHangingOrderType(2);
+            userPendingorder.setPositionType(1);
+            userPendingorder.setStockType(stockType);
+            userPendingorder.setSellOrderPrice(new BigDecimal(salePrice));
+            userPendingorderMapper.insert(userPendingorder);
         }
-        return getObjectServerResponse(request, userPosition, nowPrice, siitteBuyFee, stockType);
+        return ServerResponse.createBySuccess("操作成功",request);
     }
 
-    private ServerResponse<Object> getObjectServerResponse(HttpServletRequest request, UserPosition userPosition, BigDecimal nowPrice, BigDecimal siitteBuyFee,String stockType) {
+    public ServerResponse<Object> getObjectServerResponse(HttpServletRequest request, UserPosition userPosition, BigDecimal nowPrice, BigDecimal siitteBuyFee,String stockType) {
         userPosition.setSellOrderId(GeneratePosition.getPositionId());
         userPosition.setSellOrderPrice(nowPrice);
         userPosition.setSellOrderTime(new Date());
@@ -740,7 +813,7 @@
             pageInfo.setList(list);
             return ServerResponse.createBySuccess(pageInfo);
         }else {
-            if (stockCode.equals("HJYY")) {
+            if (null != stockCode && stockCode.equals("HJYY")) {
                 LambdaQueryWrapper<UserPosition> wrapper = getUserPositionLambdaQueryWrapper(stockCode, state, user);
                 userPositions = userPositionMapper.selectList(wrapper);
             } else {
@@ -776,10 +849,10 @@
                             userPositionVO.setIsListed(false);
                         } else {
                             userPositionVO.setIsListed(true);
-                            userPositionVO.setProfitAndLose(userPositionVO.getProfitAndLose().multiply(new BigDecimal(userPositionVO.getOrderLever())));
+                            userPositionVO.setProfitAndLose(userPositionVO.getProfitAndLose());
                         }
                     } else {
-                        userPositionVO.setProfitAndLose(userPositionVO.getProfitAndLose().multiply(new BigDecimal(userPositionVO.getOrderLever())));
+                        userPositionVO.setProfitAndLose(userPositionVO.getProfitAndLose());
                     }
                     userPositionVOS.add(userPositionVO);
                 }
@@ -903,7 +976,7 @@
         }
         PageHelper.startPage(pageNum, pageSize);
         List<UserPosition> userPositions = this.userPositionMapper.listByAgent(positionType, state,
-                userId, ids, positionSn, begin_time, end_time,null);
+                userId, ids, positionSn, begin_time, end_time,null,null);
 
         List<AgentPositionVO> agentPositionVOS = Lists.newArrayList();
         for (UserPosition position : userPositions) {
@@ -939,7 +1012,7 @@
         }
 
         List<UserPosition> userPositions = this.userPositionMapper.listByAgent(positionType, Integer.valueOf(1),
-                null, ids, null, begin_time, end_time,null);
+                null, ids, null, begin_time, end_time,null,null);
 
 
         BigDecimal order_fee_amt = new BigDecimal("0");
@@ -959,7 +1032,7 @@
         return ServerResponse.createBySuccess(agentIncomeVO);
     }
 
-    public ServerResponse listByAdmin(Integer agentId, Integer positionType, Integer state, Integer userId, String positionSn, String beginTime, String endTime, int pageNum, int pageSize,String phone) {
+    public ServerResponse listByAdmin(Integer agentId, Integer positionType, Integer state, Integer userId, String positionSn, String beginTime, String endTime, int pageNum, int pageSize,String phone,String productType) {
         PageHelper.startPage(pageNum, pageSize);
 
 
@@ -978,7 +1051,7 @@
         }
 
 
-        List<UserPosition> userPositions = this.userPositionMapper.listByAgent(positionType, state, userId, ids, positionSn, begin_time, end_time,phone);
+        List<UserPosition> userPositions = this.userPositionMapper.listByAgent(positionType, state, userId, ids, positionSn, begin_time, end_time,phone,productType);
         List<AdminPositionVO> adminPositionVOS = Lists.newArrayList();
         for (UserPosition position : userPositions) {
             AdminPositionVO adminPositionVO = assembleAdminPositionVO(position);
diff --git a/src/main/java/com/nq/service/impl/UserServiceImpl.java b/src/main/java/com/nq/service/impl/UserServiceImpl.java
index 72c2f82..71c9c4f 100644
--- a/src/main/java/com/nq/service/impl/UserServiceImpl.java
+++ b/src/main/java/com/nq/service/impl/UserServiceImpl.java
@@ -211,13 +211,13 @@
             }
             userAssetsServices.assetsByTypeAndUserId(EStockType.ST.getCode(),user.getId());
             QueryWrapper<UserAssets>  usdtQueryWrapper = new QueryWrapper<>();
-            usdtQueryWrapper.eq("accect_type","USDT");
+            usdtQueryWrapper.eq("accect_type","USD");
             usdtQueryWrapper.eq("user_id",user.getId());
             UserAssets usdtUserAssets =  userAssetsServices.getOne(usdtQueryWrapper);
             System.out.println("=========usdtUserAssets======"+JSON.toJSONString(usdtUserAssets));
             if(usdtUserAssets == null){
                 usdtUserAssets = new UserAssets();
-                usdtUserAssets.setAccectType("USDT");
+                usdtUserAssets.setAccectType("USD");
                 usdtUserAssets.setUserId(user.getId());
                 userAssetsServices.save(usdtUserAssets);
             }
diff --git a/src/main/java/com/nq/utils/task/stock/StockTask.java b/src/main/java/com/nq/utils/task/stock/StockTask.java
index 08db5ed..ad227d2 100644
--- a/src/main/java/com/nq/utils/task/stock/StockTask.java
+++ b/src/main/java/com/nq/utils/task/stock/StockTask.java
@@ -1,6 +1,7 @@
 package com.nq.utils.task.stock;
 
 import cn.hutool.core.collection.CollectionUtil;
+import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.json.JSONArray;
 import com.alibaba.fastjson2.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
@@ -22,11 +23,13 @@
 import com.nq.service.impl.UserServiceImpl;
 import com.nq.utils.ConverterUtil;
 import com.nq.utils.KeyUtils;
+import com.nq.utils.UserPointUtil;
 import com.nq.utils.http.HttpClientRequest;
 import com.nq.utils.redis.RedisKeyConstant;
 import com.nq.utils.redis.RedisKeyUtil;
 import com.nq.utils.redis.RedisShardedPoolUtils;
 import com.nq.utils.stock.GeneratePosition;
+import com.nq.vo.position.PositionProfitVO;
 import org.apache.commons.lang3.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -35,6 +38,7 @@
 import org.springframework.stereotype.Component;
 import org.springframework.web.client.RestTemplate;
 
+import javax.servlet.http.HttpServletRequest;
 import java.io.BufferedReader;
 import java.io.InputStreamReader;
 import java.io.UnsupportedEncodingException;
@@ -77,8 +81,6 @@
     @Autowired
     UserMapper userMapper;
 
-
-
     private static final Logger log = LoggerFactory.getLogger(StockTask.class);
 
 
@@ -118,31 +120,143 @@
                 pending();
             }catch (Exception e){
                 e.printStackTrace();
-                log.error("挂单定时任务报错:",e.getMessage());
+                log.error("买入挂单定时任务报错:",e.getMessage());
             }
             finally {
                 lock.unlock();  // 释放锁
             }
         } else {
             // 如果锁不可用,可以选择不执行或打印日志等
-            System.out.println("挂单定时任务  任务正在执行,跳过本次执行。");
+            System.out.println("买入挂单定时任务  任务正在执行,跳过本次执行。");
         }
     }
 
+    /**
+     * 挂单平仓
+     */
+    @Scheduled(cron = "0/10 * * * * ?")
+    public void closeOrder() {
+        ReentrantLock lock = new ReentrantLock();
+        if (lock.tryLock()) { // 尝试获取锁
+            try {
+                closeOutOrder();
+            }catch (Exception e){
+                e.printStackTrace();
+                log.error("平仓挂单定时任务报错:",e.getMessage());
+            }
+            finally {
+                lock.unlock();  // 释放锁
+            }
+        } else {
+            // 如果锁不可用,可以选择不执行或打印日志等
+            System.out.println("平仓挂单定时任务  任务正在执行,跳过本次执行。");
+        }
+    }
+
+    public void closeOutOrder() {
+        List<UserPendingorder> list = userPendingorderService.list(new LambdaQueryWrapper<>(UserPendingorder.class)
+                .eq(UserPendingorder::getPositionType, 1)
+                .eq(UserPendingorder::getHangingOrderType,2));
+        if(CollectionUtil.isNotEmpty(list)){
+            list.forEach(f->{
+                //获取当前价格
+                //股票类型 现价 数据源的处理
+                BigDecimal nowPrice = BigDecimal.ZERO;
+                if(f.getStockType().equals("ST")){
+                    nowPrice = priceServices.getNowPrice(f.getStockCode());
+                }else{
+                    nowPrice = new BigDecimal(RedisShardedPoolUtils.get(RedisKeyConstant.getRedisKey(f.getStockName())));
+                }
+                if((f.getOrderDirection().equals("买涨") && nowPrice.compareTo(f.getSellOrderPrice()) >= 0) || (f.getOrderDirection().equals("买跌") && nowPrice.compareTo(f.getSellOrderPrice()) <= 0)){
+                    closeStockTransferPositions(f);
+                }
+            });
+        }
+    }
+
+    private void closeStockTransferPositions(UserPendingorder f) {
+        UserPosition userPosition = userPositionMapper.selectOne(new LambdaQueryWrapper<>(UserPosition.class)
+                .eq(UserPosition::getPositionSn, f.getPositionSn())
+                .eq(UserPosition::getUserId, f.getUserId())
+
+        );
+
+        BigDecimal siitteBuyFee = new BigDecimal(iStockConfigServices.queryByKey(EConfigKey.SELL_HANDLING_CHARGE.getCode()).getCValue());
+        //部分平仓
+        if(f.getOrderNum() < userPosition.getOrderNum()){
+            //拆分订单
+            UserPosition position = ConverterUtil.convert(userPosition,UserPosition.class);
+            position.setId(null);
+            position.setPositionSn(KeyUtils.getUniqueKey());
+            //得到均价
+            double buyOrderPrice = position.getOrderTotalPrice().doubleValue() / position.getOrderNum().doubleValue() * position.getOrderLever();
+            position.setOrderNum(userPosition.getOrderNum()-f.getOrderNum());
+            BigDecimal positionBuyAmt = new BigDecimal(buyOrderPrice).multiply(new BigDecimal(position.getOrderNum())).divide(new BigDecimal(position.getOrderLever()));
+            position.setOrderTotalPrice(positionBuyAmt);
+            position.setBuyOrderPrice(new BigDecimal(buyOrderPrice));
+            position.setBuyOrderId(GeneratePosition.getPositionId());
+            //修改拆分订单手续费
+            BigDecimal BuyFee = new BigDecimal(iStockConfigServices.queryByKey(EConfigKey.BUY_HANDLING_CHARGE.getCode()).getCValue());
+            BigDecimal buyPrice = position.getBuyOrderPrice().multiply(new BigDecimal(position.getOrderNum()));
+            BigDecimal xsPrice = buyPrice.multiply(BuyFee);
+            position.setOrderFee(xsPrice);
+            userPositionMapper.insert(position);
+            //得到均价
+            double orderPrice = userPosition.getOrderTotalPrice().doubleValue() / userPosition.getOrderNum().doubleValue() * position.getOrderLever();
+            //修改原订单
+            userPosition.setOrderNum(f.getOrderNum());
+            BigDecimal buyAmt = new BigDecimal(orderPrice).multiply(new BigDecimal(userPosition.getOrderNum())).divide(new BigDecimal(userPosition.getOrderLever()));
+            userPosition.setOrderTotalPrice(buyAmt);
+            userPosition.setOrderFee(userPosition.getOrderFee().subtract(position.getOrderFee()));
+            userPositionMapper.updateById(userPosition);
+        }
+        getObjectServerResponse(userPosition, f.getSellOrderPrice(), siitteBuyFee, f.getStockType());
+        f.setPositionType(2);
+        userPendingorderService.updateById(f);
+    }
+
+    public void getObjectServerResponse( UserPosition userPosition, BigDecimal nowPrice, BigDecimal siitteBuyFee, String stockType) {
+        userPosition.setSellOrderId(GeneratePosition.getPositionId());
+        userPosition.setSellOrderPrice(nowPrice);
+        userPosition.setSellOrderTime(new Date());
+
+        BigDecimal sellOrderTotel = nowPrice.multiply(new BigDecimal(userPosition.getOrderNum()));
+        BigDecimal xsPrice = sellOrderTotel.multiply(siitteBuyFee);
+        userPosition.setOrderFee(userPosition.getOrderFee().add(xsPrice));
+        userPositionMapper.updateById(userPosition);
+
+        iUserAssetsServices.availablebalanceChange(stockType,
+                userPosition.getUserId(),
+                EUserAssets.CLOSE_POSITION_RETURN_SECURITY_DEPOSIT,
+                userPosition.getOrderTotalPrice(), "", "");
+        iUserAssetsServices.availablebalanceChange(stockType,
+                userPosition.getUserId(), EUserAssets.HANDLING_CHARGE,
+                xsPrice, "", "");
+
+        PositionProfitVO profitVO = UserPointUtil.getPositionProfitVO(userPosition,
+                priceServices.getNowPrice(userPosition.getStockCode()));
+
+        iUserAssetsServices.availablebalanceChange(stockType,
+                userPosition.getUserId(), EUserAssets.CLOSE_POSITION,
+                profitVO.getAllProfitAndLose(), "", "");
+    }
+
     public void pending(){
-        List<UserPendingorder> list = userPendingorderService.list(new LambdaQueryWrapper<>(UserPendingorder.class).eq(UserPendingorder::getPositionType, 1));
+        List<UserPendingorder> list = userPendingorderService.list(new LambdaQueryWrapper<>(UserPendingorder.class)
+                .eq(UserPendingorder::getPositionType, 1)
+                .eq(UserPendingorder::getHangingOrderType,1));
         if(CollectionUtil.isNotEmpty(list)){
             list.forEach(f->{
                 if(f.getStockGid().equals("ST")){
                     //获取当前价格
                     //股票类型 现价 数据源的处理
                     BigDecimal nowPrice = priceServices.getNowPrice(f.getStockCode());
-                    if(f.getBuyOrderPrice().compareTo(nowPrice) <= 0){
+                    if((f.getOrderDirection().equals("买涨") && f.getBuyOrderPrice().compareTo(nowPrice) >= 0) || (f.getOrderDirection().equals("买跌") && f.getBuyOrderPrice().compareTo(nowPrice) <= 0)){
                         stockTransferPositions(f);
                     }
                 }else{
                     String price = RedisShardedPoolUtils.get(RedisKeyConstant.getRedisKey(f.getStockName()));
-                    if(f.getBuyOrderPrice().compareTo(new BigDecimal(price)) <= 0){
+                    if((f.getOrderDirection().equals("买涨") && f.getBuyOrderPrice().compareTo(new BigDecimal(price)) >= 0) || (f.getOrderDirection().equals("买跌") && f.getBuyOrderPrice().compareTo(new BigDecimal(price)) <= 0)){
                         hjTransferPositions(f);
                     }
                 }
@@ -150,31 +264,67 @@
         }
     }
     public void hjTransferPositions(UserPendingorder userPendingorder){
+        UserPosition position = userPositionMapper.selectOne(new LambdaQueryWrapper<>(UserPosition.class)
+                .eq(UserPosition::getUserId, userPendingorder.getUserId())
+                .eq(UserPosition::getStockCode, userPendingorder.getStockCode())
+                .isNull(UserPosition::getSellOrderId)
+        );
         User user = userMapper.selectById(userPendingorder.getUserId());
         BigDecimal siteSettingBuyFee = new BigDecimal(iStockConfigServices.queryByKey(EConfigKey.BUY_HANDLING_CHARGE.getCode()).getCValue()) ;
         BigDecimal orderFree = siteSettingBuyFee.multiply(userPendingorder.getOrderTotalPrice());
         UserPosition userPosition = ConverterUtil.convert(userPendingorder, UserPosition.class);
-        userPosition.setPositionType(user.getAccountType());
-        userPosition.setId(null);
-        userPendingorder.setPositionType(0);
-        userPendingorderService.updateById(userPendingorder);
-        userPositionMapper.insert(userPosition);
-        iUserAssetsServices.availablebalanceChange("USDT", user.getId(), EUserAssets.HANDLING_CHARGE, orderFree, "", "");
+        if(ObjectUtil.isEmpty(position)){
+            userPosition.setPositionType(user.getAccountType());
+            userPosition.setId(null);
+            userPendingorder.setPositionType(0);
+            userPendingorderService.updateById(userPendingorder);
+            userPositionMapper.insert(userPosition);
+            iUserAssetsServices.availablebalanceChange("USD", user.getId(), EUserAssets.HANDLING_CHARGE, orderFree, "", "");
+        }else{
+            position.setOrderNum(position.getOrderNum()+userPosition.getOrderNum());
+            position.setOrderTotalPrice(position.getOrderTotalPrice().add(userPosition.getOrderTotalPrice()));
+            position.setOrderFee(position.getOrderFee().add(orderFree));
+            position.setBuyOrderPrice(position.getBuyOrderPrice());
+            position.setAllProfitAndLose(position.getAllProfitAndLose().add(orderFree));
+            userPositionMapper.updateById(position);
+            userPendingorder.setPositionType(0);
+            userPendingorderService.updateById(userPendingorder);
+            iUserAssetsServices.availablebalanceChange("USD", user.getId(), EUserAssets.HANDLING_CHARGE, orderFree, "", "");
+        }
     }
 
     public void stockTransferPositions(UserPendingorder userPendingorder){
+        UserPosition position = userPositionMapper.selectOne(new LambdaQueryWrapper<>(UserPosition.class)
+                .eq(UserPosition::getUserId, userPendingorder.getUserId())
+                .eq(UserPosition::getStockCode, userPendingorder.getStockCode())
+                .isNull(UserPosition::getSellOrderId)
+        );
         // 手续费率
         BigDecimal siteSettingBuyFee = new BigDecimal(iStockConfigServices.queryByKey(EConfigKey.BUY_HANDLING_CHARGE.getCode()).getCValue()) ;
         BigDecimal orderFree = siteSettingBuyFee.multiply(userPendingorder.getOrderTotalPrice());
         User user = userMapper.selectById(userPendingorder.getUserId());
         UserPosition userPosition = ConverterUtil.convert(userPendingorder, UserPosition.class);
-        userPosition.setPositionType(user.getAccountType());
-        userPosition.setId(null);
-        userPendingorder.setPositionType(0);
-        userPendingorderService.updateById(userPendingorder);
-        userPositionMapper.insert(userPosition);
-        //挂单成功扣除手续费
-        iUserAssetsServices.availablebalanceChange("ST", user.getId(), EUserAssets.HANDLING_CHARGE, orderFree, "", "");
+        if(ObjectUtil.isEmpty(position)){
+            userPosition.setPositionType(user.getAccountType());
+            userPosition.setId(null);
+            userPendingorder.setPositionType(0);
+            userPendingorderService.updateById(userPendingorder);
+            userPositionMapper.insert(userPosition);
+            //挂单成功扣除手续费
+            iUserAssetsServices.availablebalanceChange("ST", user.getId(), EUserAssets.HANDLING_CHARGE, orderFree, "", "");
+        }else{
+            position.setOrderNum(position.getOrderNum()+userPosition.getOrderNum());
+            position.setOrderTotalPrice(position.getOrderTotalPrice().add(userPosition.getOrderTotalPrice()));
+            position.setOrderFee(position.getOrderFee().add(orderFree));
+            double divide = position.getOrderTotalPrice().doubleValue() / position.getOrderNum();
+            position.setBuyOrderPrice(new BigDecimal(divide*position.getOrderLever()));
+            position.setAllProfitAndLose(position.getAllProfitAndLose().add(orderFree));
+            userPositionMapper.updateById(position);
+            userPendingorder.setPositionType(0);
+            userPendingorderService.updateById(userPendingorder);
+            //挂单成功扣除手续费
+            iUserAssetsServices.availablebalanceChange("ST", user.getId(), EUserAssets.HANDLING_CHARGE, orderFree, "", "");
+        }
     }
 
     //最新价格url
diff --git a/src/main/resources/mapper/UserPositionMapper.xml b/src/main/resources/mapper/UserPositionMapper.xml
index ca7b635..315e677 100644
--- a/src/main/resources/mapper/UserPositionMapper.xml
+++ b/src/main/resources/mapper/UserPositionMapper.xml
@@ -435,6 +435,9 @@
       <if test="userId != null and userId != ''">
         AND user_id = #{userId}
       </if>
+      <if test="productType != null and productType != ''">
+        AND stock_gid = #{productType}
+      </if>
       <if test="positionSn != null and positionSn != ''">
         AND position_sn LIKE CONCAT('%', #{positionSn}, '%')
       </if>

--
Gitblit v1.9.3