1
zj
2024-05-06 49770c755aa288c72d6977ff2fd1f55f653b99bf
1
13 files modified
4 files added
850 ■■■■ changed files
src/main/java/com/nq/controller/backend/AdminController.java 22 ●●●●● patch | view | raw | blame | history
src/main/java/com/nq/controller/protol/UserController.java 9 ●●●●● patch | view | raw | blame | history
src/main/java/com/nq/dao/ApplyLeverMapper.java 7 ●●●●● patch | view | raw | blame | history
src/main/java/com/nq/enums/EUserAssets.java 1 ●●●● patch | view | raw | blame | history
src/main/java/com/nq/pojo/ApplyLever.java 37 ●●●●● patch | view | raw | blame | history
src/main/java/com/nq/pojo/MoneyLog.java 5 ●●●●● patch | view | raw | blame | history
src/main/java/com/nq/pojo/User.java 2 ●●● patch | view | raw | blame | history
src/main/java/com/nq/pojo/UserAssets.java 3 ●●●●● patch | view | raw | blame | history
src/main/java/com/nq/pojo/reponse/RUserAssets.java 3 ●●●●● patch | view | raw | blame | history
src/main/java/com/nq/service/IApplyLeverServices.java 17 ●●●●● patch | view | raw | blame | history
src/main/java/com/nq/service/IUserPositionService.java 2 ●●●●● patch | view | raw | blame | history
src/main/java/com/nq/service/impl/ApplyLeverServicesimpl.java 90 ●●●●● patch | view | raw | blame | history
src/main/java/com/nq/service/impl/UserAssetsServices.java 81 ●●●● patch | view | raw | blame | history
src/main/java/com/nq/service/impl/UserPositionServiceImpl.java 292 ●●●● patch | view | raw | blame | history
src/main/java/com/nq/service/impl/UserServiceImpl.java 72 ●●●● patch | view | raw | blame | history
src/main/java/com/nq/service/impl/UserStockSubscribeServiceImpl.java 78 ●●●●● patch | view | raw | blame | history
src/main/java/com/nq/utils/task/stock/StockTask.java 129 ●●●●● patch | view | raw | blame | history
src/main/java/com/nq/controller/backend/AdminController.java
@@ -72,6 +72,10 @@
    @Autowired
    IUserAssetsServices iUserAssetsServices;
    @Autowired
    IApplyLeverServices iApplyLeverServices;
    //分页查询管理设置 所有管理列表数据及模糊查询
    @RequestMapping({"list.do"})
    @ResponseBody
@@ -343,4 +347,22 @@
        return  iUserAssetsServices.updateUserAssets(id,amt);
    }
    @RequestMapping({"examineApplyLever.do"})
    @ResponseBody
    public ServerResponse examineApplyLever(@RequestParam(value = "id", required = true) String id,
                                            @RequestParam(value = "state", defaultValue = "1") String state,
                                            HttpServletRequest request) {
        return this.iApplyLeverServices.examineApplyLever(id,state,request);
    }
    @RequestMapping({"queryApplyLever.do"})
    @ResponseBody
    public ServerResponse queryApplyLever(@RequestParam(value = "phone", required = false) String adminName,
                                          @RequestParam(value = "pageNum", defaultValue = "1") int pageNum,
                                          @RequestParam(value = "pageSize", defaultValue = "10") int pageSize,
                                          HttpServletRequest request
    ) {
        return this.iApplyLeverServices.queryApplyLever(adminName,pageNum,pageSize, request);
    }
}
src/main/java/com/nq/controller/protol/UserController.java
@@ -4,6 +4,7 @@
import com.google.common.collect.Maps;
import com.nq.common.ServerResponse;
import com.nq.enums.EStockType;
import com.nq.pojo.ApplyLever;
import com.nq.pojo.StockSubscribe;
import com.nq.pojo.UserStockSubscribe;
import com.nq.service.*;
@@ -56,6 +57,9 @@
    @Autowired
    IUserRechargeService iUserRechargeService;
    @Autowired
    IApplyLeverServices iApplyLeverServices;
    //添加到自选股
    @RequestMapping({"addOption.do"})
@@ -349,5 +353,10 @@
        return ServerResponse.createBySuccess(rateServices.currencyRate(EStockType.getEStockTypeByCode(stockCode), EStockType.getEStockTypeByCode(toType)));
    }
    @RequestMapping({"applyLever.do"})
    @ResponseBody
    public ServerResponse applyLever(ApplyLever applyLever, HttpServletRequest request) {
        return iApplyLeverServices.applyLever(applyLever,request);
    }
}
src/main/java/com/nq/dao/ApplyLeverMapper.java
New file
@@ -0,0 +1,7 @@
package com.nq.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.nq.pojo.ApplyLever;
public interface ApplyLeverMapper extends BaseMapper<ApplyLever> {
}
src/main/java/com/nq/enums/EUserAssets.java
@@ -12,6 +12,7 @@
    CLOSE_POSITION_RETURN_SECURITY_DEPOSIT("CLOSE_POSITION_RETURN_SECURITY","平仓返回保证金"),
    CLOSE_POSITION("CLOSE_POSITION","平仓"),
    CONSTRAINT_CLOSE_POSITION("CONSTRAINT_CLOSE_POSITION","强制平仓"),
    BUY("BUY","购买"),
    WITHDRAW("WITHDRAW","提现"),
src/main/java/com/nq/pojo/ApplyLever.java
New file
@@ -0,0 +1,37 @@
package com.nq.pojo;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
@Data
public class ApplyLever {
    @TableId(value = "id",type = IdType.AUTO)
    private Integer id;
    /**
     *
     */
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date createTime;
    // 用户id
    private String userId;
    // 用户手机号码
    private String phone;
    // 杠杆
    private String lever;
    private String state;
    private String descs;
}
src/main/java/com/nq/pojo/MoneyLog.java
@@ -2,7 +2,10 @@
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.util.Date;
@Data
public class MoneyLog {
@@ -18,6 +21,8 @@
    private String userId;
    private String symbol;
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private Date createTime;
}
src/main/java/com/nq/pojo/User.java
@@ -23,7 +23,7 @@
    private Integer accountType;
    private String lever;
    private String recomPhone;
    private Integer isLock;
    private Integer isLogin;
src/main/java/com/nq/pojo/UserAssets.java
@@ -47,4 +47,7 @@
    // 冻结金额
    private BigDecimal freezeMoney;
    // 累计盈亏 0 正 1 负
    private Integer isZf;
}
src/main/java/com/nq/pojo/reponse/RUserAssets.java
@@ -52,4 +52,7 @@
    private String symbol;
    private String symbolCode;
    // 累计盈亏 0 正 1 负
    private Integer isZf;
}
src/main/java/com/nq/service/IApplyLeverServices.java
New file
@@ -0,0 +1,17 @@
package com.nq.service;
import com.nq.common.ServerResponse;
import com.nq.pojo.ApplyLever;
import javax.servlet.http.HttpServletRequest;
public interface IApplyLeverServices {
    ServerResponse  applyLever(ApplyLever applyLever, HttpServletRequest request);
    ServerResponse  examineApplyLever(String  id,String states, HttpServletRequest request);
    ServerResponse  queryApplyLever(String phone, Integer page,Integer pageSize,HttpServletRequest request);
}
src/main/java/com/nq/service/IUserPositionService.java
@@ -80,4 +80,6 @@
    ServerResponse buyDz(String stockCode, String password, Integer num, HttpServletRequest request) throws Exception;
  ServerResponse buyStockDzList(HttpServletRequest request);
  void stockConstraint(List<UserPosition> userPositions);
}
src/main/java/com/nq/service/impl/ApplyLeverServicesimpl.java
New file
@@ -0,0 +1,90 @@
package com.nq.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.nq.common.ServerResponse;
import com.nq.dao.ApplyLeverMapper;
import com.nq.dao.UserMapper;
import com.nq.pojo.ApplyLever;
import com.nq.pojo.User;
import com.nq.service.IApplyLeverServices;
import com.nq.service.IUserService;
import org.apache.http.util.TextUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;
@Service
public class ApplyLeverServicesimpl implements IApplyLeverServices {
    @Resource
    ApplyLeverMapper applyLeverMapper;
    @Resource
    IUserService userService;
    @Resource
    UserMapper userMapper;
    @Override
    public ServerResponse applyLever(ApplyLever applyLever, HttpServletRequest request) {
        QueryWrapper<ApplyLever> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id",userService.getCurrentUser(request).getId());
        queryWrapper.ne("state",2);
        if(applyLeverMapper.selectCount(queryWrapper)>0){
            return ServerResponse.createByErrorMsg("你已经申请杠杆了",request);
        }
        User user = userService.getCurrentUser(request);
        applyLever.setPhone(user.getPhone());
        applyLever.setUserId(user.getId()+"");
        applyLever.setState("0");
        applyLever.setCreateTime(new Date());
        if(applyLeverMapper.insert(applyLever)>0){
            return ServerResponse.createBySuccess("申请成功,请联系客服",request);
        }else{
            return ServerResponse.createByErrorMsg("申请失败",request);
        }
    }
    @Transactional
    @Override
    public ServerResponse examineApplyLever(String  id,String states, HttpServletRequest request) {
        ApplyLever applyLever = applyLeverMapper.selectById(id);
        applyLever.setState(states);
        applyLeverMapper.updateById(applyLever);
       User user =  userMapper.selectById(applyLever.getUserId());
       user.setLever(applyLever.getLever());
       userMapper.updateById(user);
       return ServerResponse.createBySuccess();
    }
    @Override
    public ServerResponse queryApplyLever(String phone, Integer page, Integer pageSize, HttpServletRequest request) {
        Integer userId = null;
        Page<ApplyLever> page1 = new Page<>(page, pageSize);
        if(!TextUtils.isEmpty(phone)){
            QueryWrapper<User> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("phone",phone);
            User user = userMapper.selectOne(queryWrapper);
            if(user != null ){
                userId = user.getId();
            }else{
                QueryWrapper<ApplyLever> queryWrapper1 = new QueryWrapper<>();
                queryWrapper1.eq("user_id",phone);
                return ServerResponse.createBySuccess(applyLeverMapper.selectPage(page1,queryWrapper1));
            }
        }
        QueryWrapper<ApplyLever> queryWrapper1 = new QueryWrapper<>();
        if(userId != null){
            queryWrapper1.eq("user_id",userId);
        }
        queryWrapper1.orderByDesc("create_time");
       return ServerResponse.createBySuccess(applyLeverMapper.selectPage(page1,queryWrapper1));
    }
}
src/main/java/com/nq/service/impl/UserAssetsServices.java
@@ -13,6 +13,7 @@
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Objects;
@@ -91,28 +92,59 @@
        String type = eUserAssets.getDesc();
        String before = userAssets.getAvailableBalance().toString();
        String accectType = userAssets.getAccectType();
       if(Objects.equals(eUserAssets.getCode(), EUserAssets.BUY.getCode())){
        if(Objects.equals(eUserAssets.getCode(), EUserAssets.BUY.getCode())){
            userAssets.setAvailableBalance(userAssets.getAvailableBalance().add(amount));
            userAssets.setFreezeMoney(userAssets.getFreezeMoney().add(amount.negate()));
        }else if(Objects.equals(eUserAssets.getCode(), EUserAssets.CLOSE_POSITION.getCode())){
            userAssets.setAvailableBalance(userAssets.getAvailableBalance().add(amount));
            userAssets.setCumulativeProfitAndLoss(userAssets.getCumulativeProfitAndLoss().add(amount.abs()));
            extracted(amount, userAssets);
        }else  if(Objects.equals(eUserAssets.getCode(), EUserAssets.CLOSE_POSITION_RETURN_SECURITY_DEPOSIT.getCode())){
            userAssets.setAvailableBalance(userAssets.getAvailableBalance().add(amount));
            if(userAssets.getAmountToBeCovered().compareTo(BigDecimal.ZERO) > 0){
                BigDecimal availableBalance = amount.subtract(userAssets.getAmountToBeCovered());
                if(availableBalance.compareTo(BigDecimal.ZERO) > 0){
                    userAssets.setAvailableBalance(userAssets.getAvailableBalance().add(availableBalance));
                    userAssets.setAmountToBeCovered(BigDecimal.ZERO);
                }else{
                    BigDecimal amountToBeCovered = userAssets.getAmountToBeCovered().subtract(amount);
                    userAssets.setAmountToBeCovered(amountToBeCovered);
                }
            }else{
                userAssets.setAvailableBalance(userAssets.getAvailableBalance().add(amount));
            }
            userAssets.setFreezeMoney(userAssets.getFreezeMoney().subtract(amount));
        }else if(Objects.equals(eUserAssets.getCode(), EUserAssets.CALCULATE_PROFIT_AND_LOSS.getCode())){
            userAssets.setCumulativeProfitAndLoss(userAssets.getProfitAndLoss().add(amount.abs()));
            extracted(amount, userAssets);
        }else if(Objects.equals(eUserAssets.getCode(), EUserAssets.TRANSFER.getCode())){
            userAssets.setAvailableBalance(userAssets.getAvailableBalance().add(amount));
           eUserAssets.setDesc(desc);
            eUserAssets.setDesc(desc);
        }else if(Objects.equals(eUserAssets.getCode(), EUserAssets.TOP_UP.getCode())){
            userAssets.setAvailableBalance(userAssets.getAvailableBalance().add(amount));
            if(userAssets.getAmountToBeCovered().compareTo(BigDecimal.ZERO) > 0){
                BigDecimal availableBalance = amount.subtract(userAssets.getAmountToBeCovered());
                if(availableBalance.compareTo(BigDecimal.ZERO) > 0){
                    userAssets.setAvailableBalance(userAssets.getAvailableBalance().add(availableBalance));
                    userAssets.setAmountToBeCovered(BigDecimal.ZERO);
                }else{
                    BigDecimal amountToBeCovered = userAssets.getAmountToBeCovered().subtract(amount);
                    userAssets.setAmountToBeCovered(amountToBeCovered);
                }
            }else{
                userAssets.setAvailableBalance(userAssets.getAvailableBalance().add(amount));
            }
        }else if(Objects.equals(eUserAssets.getCode(), EUserAssets.WITHDRAW.getCode())){
            userAssets.setAvailableBalance(userAssets.getAvailableBalance().add(amount));
        }else if(Objects.equals(eUserAssets.getCode(), EUserAssets.HANDLING_CHARGE.getCode())){
           userAssets.setHandlingCharge(userAssets.getHandlingCharge().add(amount.abs()));
           userAssets.setAvailableBalance(userAssets.getAvailableBalance().add(amount.negate()));
       }
            userAssets.setHandlingCharge(userAssets.getHandlingCharge().add(amount.abs()));
            userAssets.setAvailableBalance(userAssets.getAvailableBalance().add(amount.negate()));
            extracted(amount.negate(),userAssets);
        }else if(Objects.equals(eUserAssets.getCode(), EUserAssets.CONSTRAINT_CLOSE_POSITION.getCode())){
            userAssets.setFreezeMoney(userAssets.getFreezeMoney().subtract(amount));
            if(userAssets.getIsZf() == 0){
                userAssets.setCumulativeProfitAndLoss(userAssets.getCumulativeProfitAndLoss().subtract(amount));
            }else{
                userAssets.setCumulativeProfitAndLoss(userAssets.getCumulativeProfitAndLoss().add(amount));
            }
            extracted(userAssets);
        }
        String  after =  userAssets.getAvailableBalance().toString();
        MoneyLog moneyLog = new MoneyLog();
        moneyLog.setDescs(eUserAssets.getDesc());
@@ -123,7 +155,38 @@
        moneyLog.setType(eUserAssets.getCode());
        moneyLog.setUserId(userId+"");
        moneyLog.setSymbol(EStockType.getEStockTypeByCode(accetType).getSymbol());
        moneyLog.setCreateTime(new Date());
        moneyLogMapper.insert(moneyLog);
        return userAssetsMapper.updateById(userAssets)>1;
    }
    //只要涉及到cumulativeProfitAndLoss变动重新设置状态
    private static void extracted(UserAssets userAssets) {
        if(userAssets.getCumulativeProfitAndLoss().compareTo(BigDecimal.ZERO) >= 0){
            userAssets.setIsZf(0);
        }else{
            userAssets.setIsZf(1);
            userAssets.setCumulativeProfitAndLoss(userAssets.getCumulativeProfitAndLoss().abs());
        }
    }
    private static void extracted(BigDecimal amount, UserAssets userAssets) {
        if(userAssets.getIsZf() == 1){
            userAssets.setCumulativeProfitAndLoss(userAssets.getCumulativeProfitAndLoss().negate());
        }
        if(userAssets.getIsZf() == 0){
            if(amount.compareTo(BigDecimal.ZERO) >= 0){
                userAssets.setCumulativeProfitAndLoss(userAssets.getCumulativeProfitAndLoss().add(amount.abs()));
            }else{
                userAssets.setCumulativeProfitAndLoss(userAssets.getCumulativeProfitAndLoss().subtract(amount.abs()));
            }
        }else{
            if(amount.compareTo(BigDecimal.ZERO) >= 0){
                userAssets.setCumulativeProfitAndLoss(userAssets.getCumulativeProfitAndLoss().add(amount.abs()));
            }else{
                userAssets.setCumulativeProfitAndLoss(userAssets.getCumulativeProfitAndLoss().subtract(amount.abs()));
            }
        }
        extracted(userAssets);
    }
}
src/main/java/com/nq/service/impl/UserPositionServiceImpl.java
@@ -1,5 +1,6 @@
package com.nq.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.nq.dao.*;
import com.nq.enums.EStockType;
@@ -31,6 +32,9 @@
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.temporal.ChronoUnit;
import java.util.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
@@ -109,51 +113,53 @@
    @Autowired
    IPriceServices priceServices;
    @Autowired
    UserAssetsMapper userAssetsMapper;
    @Transactional
    public ServerResponse buy(Integer stockId, Integer buyNum, Integer buyType, Integer lever, BigDecimal profitTarget, BigDecimal stopTarget, HttpServletRequest request)  {
    public ServerResponse buy(Integer stockId, Integer buyNum, Integer buyType, Integer lever, BigDecimal profitTarget, BigDecimal stopTarget, HttpServletRequest request) {
        SiteProduct siteProduct = iSiteProductService.getProductSetting();
        User user = this.iUserService.getCurrentRefreshUser(request);
        if (siteProduct.getRealNameDisplay() && (StringUtils.isBlank(user.getRealName()) || StringUtils.isBlank(user.getIdCard()))) {
            return ServerResponse.createByErrorMsg("订单失败,请先实名认证",request);
        if (siteProduct.getRealNameDisplay() && user.getIsActive() != 2) {
            return ServerResponse.createByErrorMsg("订单失败,请先实名认证", request);
        }
         SiteSetting siteSetting = this.iSiteSettingService.getSiteSetting();
         // 手续费率
          BigDecimal siteSettingBuyFee = siteSetting.getBuyFee();
        SiteSetting siteSetting = iSiteSettingService.getSiteSetting();
        // 手续费率
        BigDecimal siteSettingBuyFee = siteSetting.getBuyFee();
        if (siteProduct.getRealNameDisplay() && user.getIsLock().intValue() == 1) {
            return ServerResponse.createByErrorMsg("订单失败,帐户已被锁定",request);
            return ServerResponse.createByErrorMsg("订单失败,帐户已被锁定", request);
        }
        Stock stock = stockMapper.selectByPrimaryKey(stockId);
        if (stock == null) {
            return ServerResponse.createByErrorMsg("订单失败,股票代码不存在",request);
            return ServerResponse.createByErrorMsg("订单失败,股票代码不存在", request);
        }
        //判断股票是否在可交易时间段
        Boolean b = tradingHourService.timeCheck(stock.getStockCode());
        if (!b) {
            return ServerResponse.createByErrorMsg("订单失败,不在交易时间之内",request);
            return ServerResponse.createByErrorMsg("订单失败,不在交易时间之内", request);
        }
        UserAssets userAssets = iUserAssetsServices.assetsByTypeAndUserId(stock.getStockType(), user.getId());
        if (stock.getIsLock() != 0) {
            return ServerResponse.createByErrorMsg("订单失败,股票被锁定",request);
            return ServerResponse.createByErrorMsg("订单失败,股票被锁定", request);
        }
        //股票类型 现价 数据源的处理
        BigDecimal  nowPrice = priceServices.getNowPrice(stock.getStockCode());
        BigDecimal nowPrice = priceServices.getNowPrice(stock.getStockCode());
        if (nowPrice.compareTo(new BigDecimal("0")) == 0) {
            return ServerResponse.createByErrorMsg("报价0,请稍后再试",request);
            return ServerResponse.createByErrorMsg("报价0,请稍后再试", request);
        }
        BigDecimal buyAmt = nowPrice.multiply(new BigDecimal(buyNum));
        BigDecimal orderFree =  siteSettingBuyFee.multiply(buyAmt);
        BigDecimal buyAmt = nowPrice.multiply(new BigDecimal(buyNum)).divide(new BigDecimal(lever));
        BigDecimal orderFree = siteSettingBuyFee.multiply(buyAmt);
        UserAssets userAssets = iUserAssetsServices.assetsByTypeAndUserId(stock.getStockType(),user.getId());
        if(userAssets.getAvailableBalance().compareTo(buyAmt.add(orderFree))<0){
            return ServerResponse.createByErrorMsg("订单失败,余额不足",request);
        if (userAssets.getAvailableBalance().compareTo(buyAmt.add(orderFree)) < 0) {
            return ServerResponse.createByErrorMsg("订单失败,配资不足", request);
        }
        UserPosition userPosition = new UserPosition();
        if (profitTarget != null && profitTarget.compareTo(new BigDecimal("0")) > 0) {
@@ -193,9 +199,9 @@
        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);
        iUserAssetsServices.availablebalanceChange(stock.getStockType(), user.getId(), EUserAssets.BUY, buyAmt.negate(), "", "");
        iUserAssetsServices.availablebalanceChange(stock.getStockType(), user.getId(), EUserAssets.HANDLING_CHARGE, orderFree, "", "");
        return ServerResponse.createBySuccessMsg("下单成功", request);
    }
@@ -290,30 +296,30 @@
    @Transactional
    public ServerResponse sell(String positionSn, int doType,HttpServletRequest request){
    public ServerResponse sell(String positionSn, int doType, HttpServletRequest request) {
        UserPosition userPosition = this.userPositionMapper.findPositionBySn(positionSn);
        BigDecimal siitteBuyFee = iSiteSettingService.getSiteSetting().getBuyFee();
        Boolean b = tradingHourService.timeCheck(userPosition.getStockCode());
        if (!b) {
            return ServerResponse.createByErrorMsg("订单失败,不在交易时间之内",request);
        }
        SiteSetting siteSetting = iSiteSettingService.getSiteSetting();
        // 手续费率
        BigDecimal siitteBuyFee = siteSetting.getSellFee();
        if (userPosition == null) {
            return ServerResponse.createByErrorMsg("平仓失败,订单不存在",request);
            return ServerResponse.createByErrorMsg("平仓失败,订单不存在", request);
        }
        User user = this.userMapper.selectById(userPosition.getUserId());
        if (user == null) {
            return ServerResponse.createByErrorMsg("平仓失败,用户不存在",request);
            return ServerResponse.createByErrorMsg("平仓失败,用户不存在", request);
        }
        if (userPosition.getSellOrderId() != null) {
            return ServerResponse.createByErrorMsg("平仓失败, 订单已平仓",request);
            return ServerResponse.createByErrorMsg("平仓失败, 订单已平仓", request);
        }
        if (1 == userPosition.getIsLock().intValue()) {
            return ServerResponse.createByErrorMsg("this order is closed " + userPosition.getLockMsg());
        }
        Stock stock = stockMapper.selectOne(new QueryWrapper<Stock>().eq("stock_code", userPosition.getStockCode()));
        BigDecimal  nowPrice = priceServices.getNowPrice(userPosition.getStockCode());
        BigDecimal nowPrice = priceServices.getNowPrice(userPosition.getStockCode());
        if (nowPrice.compareTo(new BigDecimal("0")) != 1) {
            return ServerResponse.createByErrorMsg("报价0,平仓失败,请稍后再试",request);
            return ServerResponse.createByErrorMsg("报价0,平仓失败,请稍后再试", request);
        }
        userPosition.setSellOrderId(GeneratePosition.getPositionId());
        userPosition.setSellOrderPrice(nowPrice);
@@ -323,16 +329,20 @@
        BigDecimal xsPrice = sellOrderTotel.multiply(siitteBuyFee);
        userPositionMapper.updateById(userPosition);
        userAssetsServices.availablebalanceChange(stock.getStockType(),
                userPosition.getUserId(),EUserAssets.CLOSE_POSITION_RETURN_SECURITY_DEPOSIT,
                userPosition.getOrderTotalPrice(),"","");
                userPosition.getUserId(),
                EUserAssets.CLOSE_POSITION_RETURN_SECURITY_DEPOSIT,
                userPosition.getOrderTotalPrice(), "", "");
        userAssetsServices.availablebalanceChange(stock.getStockType(),
                userPosition.getUserId(),EUserAssets.HANDLING_CHARGE,
                xsPrice,"","");
                userPosition.getUserId(), EUserAssets.HANDLING_CHARGE,
                xsPrice, "", "");
        PositionProfitVO profitVO =  UserPointUtil.getPositionProfitVO(userPosition,priceServices.getNowPrice(userPosition.getStockCode()));
        userAssetsServices.availablebalanceChange(stock.getStockType(),userPosition.getUserId(),EUserAssets.CLOSE_POSITION,
                profitVO.getAllProfitAndLose() ,"","");
        return ServerResponse.createBySuccessMsg("平仓成功!",request);
        PositionProfitVO profitVO = UserPointUtil.getPositionProfitVO(userPosition,
                priceServices.getNowPrice(userPosition.getStockCode()));
        userAssetsServices.availablebalanceChange(stock.getStockType(),
                userPosition.getUserId(), EUserAssets.CLOSE_POSITION,
                profitVO.getAllProfitAndLose(), "", "");
        return ServerResponse.createBySuccessMsg("平仓成功!", request);
    }
    @Transactional
@@ -355,7 +365,7 @@
        List<UserPosition> userPositionList = userPositionMapper.selectList(queryWrapper);
        for (int i = 0; i < userPositionList.size(); i++) {
            sell(userPositionList.get(i).getPositionSn(),0);
            sell(userPositionList.get(i).getPositionSn(),0,request);
        }
        return ServerResponse.createBySuccessMsg("平仓成功!");
    }
@@ -520,7 +530,10 @@
        PageHelper.startPage(pageNum, pageSize);
        List<UserPosition> userPositions;
        userPositions   = userPositionMapper.
        userPositions = userPositionMapper.
                findMyPositionByCodeAndSpell(user.getId(),
                        stockCode, stockSpell,
                        state, stockType);
@@ -529,7 +542,9 @@
        List<UserPositionVO> userPositionVOS = Lists.newArrayList();
        if (userPositions.size() > 0) {
            for (UserPosition position : userPositions) {
                UserPositionVO userPositionVO = UserPointUtil.assembleUserPositionVO(position,priceServices.getNowPrice(position.getStockCode()));
                UserPositionVO userPositionVO = UserPointUtil.assembleUserPositionVO(position, priceServices.getNowPrice(position.getStockCode()));
                userPositionVO.setOrderTotalPrice(userPositionVO.getOrderTotalPrice().multiply(new BigDecimal(userPositionVO.getOrderLever())));
                userPositionVO.setProfitAndLose(userPositionVO.getProfitAndLose().multiply(new BigDecimal(userPositionVO.getOrderLever())));
                userPositionVOS.add(userPositionVO);
            }
        }
@@ -1127,26 +1142,25 @@
        if (userStockSubscribe == null) {
            return ServerResponse.createByErrorMsg("无该申购记录");
        }
        StockSubscribe stockSubscribe = stockSubscribeMapper.selectOne(new QueryWrapper<StockSubscribe>().eq("code", userStockSubscribe.getNewCode()));
        StockSubscribe stockSubscribe = stockSubscribeMapper.selectOne(new QueryWrapper<StockSubscribe>().eq("code", userStockSubscribe.getNewCode()).eq("type",userStockSubscribe.getType()));
        if (userStockSubscribe == null) {
            return ServerResponse.createByErrorMsg("该新股不存在");
        }
        if (userStockSubscribe.getStatus() == 4 || userStockSubscribe.getStatus() == 3 && stockSubscribe.getType() == 2) {
//                String sinaStock = SinaStockApi.getSinaStock(stockSubscribe.getStockType()+userStockSubscribe.getNewCode());
//                String[] arrayOfString = sinaStock.split(",");
//                 if (arrayOfString.length < 10){
//                 return ServerResponse.createByErrorMsg("数据源无该新股数据,转持仓失败");
//                 }
            Stock stock = stockMapper.selectOne(new LambdaQueryWrapper<Stock>().eq(Stock::getStockCode, userStockSubscribe.getNewCode()));
            if(null == stock){
                return ServerResponse.createByErrorMsg("该新股不存在");
            }
            UserPosition userPosition = new UserPosition();
            userPosition.setPositionType(1);
            userPosition.setPositionSn(KeyUtils.getUniqueKey());
            userPosition.setUserId(userStockSubscribe.getUserId());
            userPosition.setNickName(userStockSubscribe.getRealName());
            userPosition.setAgentId(userStockSubscribe.getAgentId());
            userPosition.setStockCode(userStockSubscribe.getNewCode());
            userPosition.setStockCode(stock.getStockCode());
            userPosition.setStockSpell(stock.getStockSpell());
            userPosition.setStockName(userStockSubscribe.getNewName());
            userPosition.setStockGid(stockSubscribe.getStockType() + userStockSubscribe.getNewCode());
            userPosition.setStockGid(stock.getStockType());
            userPosition.setBuyOrderId(GeneratePosition.getPositionId());
            userPosition.setBuyOrderTime(new Date());
@@ -1159,7 +1173,7 @@
            userPosition.setIsLock(Integer.valueOf(0));
            userPosition.setOrderLever(10);
            userPosition.setOrderLever(1);
            //递延费特殊处理
@@ -1181,14 +1195,6 @@
            log.info("用户购买印花税(配资后总资金 * 百分比) = {}", buy_yhs_amt);
            userPosition.setOrderSpread(buy_yhs_amt);
            //            SiteSpread siteSpread = iSiteSpreadService.findSpreadRateOne(new BigDecimal(stock_crease), buy_amt, stock.getStockCode(), now_price);
            //            BigDecimal spread_rate_amt = new BigDecimal("0");
            //            if(siteSpread != null){
            //                spread_rate_amt = buy_amt.multiply(siteSpread.getSpreadRate()).setScale(2, 4);
            //                log.info("用户购买点差费(配资后总资金 * 百分比{}) = {}", siteSpread.getSpreadRate(), spread_rate_amt);
            //            } else{
            //                log.info("用户购买点差费(配资后总资金 * 百分比{}) = {}", "设置异常", spread_rate_amt);
            //            }
            BigDecimal spread_rate_amt = new BigDecimal(0);
            userPosition.setSpreadRatePrice(spread_rate_amt);
@@ -1206,13 +1212,17 @@
            int ret = 0;
            ret = this.userPositionMapper.insert(userPosition);
            UserAssets userAssets = iUserAssetsServices.assetsByTypeAndUserId(stock.getStockType(), userPosition.getUserId());
            if(null == userAssets){
                return ServerResponse.createByErrorMsg("新股转持仓失败");
            }
            userAssetsMapper.updateById(userAssets);
            if (ret > 0) {
                userStockSubscribe.setStatus(5);
                userStockSubscribeMapper.update1(userStockSubscribe);
                if (userStockSubscribe.getType() == 1 || userStockSubscribe.getType() == 2) {
                    User user = userMapper.selectById(userStockSubscribe.getUserId());
                    ret = userMapper.updateByPrimaryKey(user);
                    ret = userMapper.updateById(user);
                }
                if (ret > 0) {
                    return ServerResponse.createBySuccessMsg("新股转持仓成功");
@@ -1758,6 +1768,162 @@
    }
    @Override
    @Transactional
    public void stockConstraint(List<UserPosition> list) {
        SiteSetting siteSetting = iSiteSettingService.getSiteSetting();
        for (UserPosition position : list) {
            Stock stock = stockMapper.selectOne(new LambdaQueryWrapper<Stock>().eq(Stock::getStockCode, position.getStockCode()));
            UserAssets userAssets = userAssetsMapper.selectOne(new LambdaQueryWrapper<UserAssets>()
                    .eq(UserAssets::getUserId, position.getUserId())
                    .eq(UserAssets::getAccectType, stock.getStockType())
            );
            if(userAssets.getAmountToBeCovered().compareTo(BigDecimal.ZERO) > 0){
                continue;
            }
            //平仓检查
            Result result = getResult(position);
            if (result == null) continue;
            Integer liquidation = 0;
            liquidation = isLiquidation(position, result.signum, result.profit, liquidation);
            if(liquidation != 0){
                extracted(position, result.nowPrice, result.stock,liquidation);
            }
        }
    }
    private Result getResult(UserPosition position) {
        // 检查订单是否存在
        if (position == null) {
            log.info("订单不存在,订单id: {}", position.getId());
            return null;
        }
        // 检查用户是否存在
        User user = this.userMapper.selectById(position.getUserId());
        if (user == null) {
            log.info("用户不存在,订单id: {}", position.getId());
            return null;
        }
        //判断订单
        if (1 == position.getIsLock().intValue()) {
            log.info("订单已终止,订单id: {}", position.getId());
            return null;
        }
        Stock stock = stockMapper.selectOne(new QueryWrapper<Stock>().eq("stock_code", position.getStockCode()));
        BigDecimal nowPrice = priceServices.getNowPrice(position.getStockCode());
        //判断订单是否已到强制平仓价格
        BigDecimal purchaseAmount = position.getBuyOrderPrice().multiply(new BigDecimal(position.getOrderNum()));// 买入价总额
        BigDecimal nowPriceAmount = nowPrice.multiply(new BigDecimal(position.getOrderNum())); // 现价总额
        BigDecimal profit = nowPriceAmount.subtract(purchaseAmount);//利润
        int signum = profit.signum();  // -1, 0, 1,分别表示 负数、零、正数
        Result result = new Result(stock, nowPrice, profit, signum);
        return result;
    }
    private static class Result {
        public final Stock stock;//股票
        public final BigDecimal nowPrice;//现价
        public final BigDecimal profit;//利润
        public final int signum;// -1, 0, 1,分别表示 负数、零、正数
        public Result(Stock stock, BigDecimal nowPrice, BigDecimal profit, int signum) {
            this.stock = stock;
            this.nowPrice = nowPrice;
            this.profit = profit;
            this.signum = signum;
        }
    }
    //判断平仓
    private Integer isLiquidation(UserPosition position, int signum, BigDecimal profit, Integer liquidation) {
        //-1强平 0未触发 1止损强平 2止盈强平
        //最新报价
        BigDecimal nowPrice = priceServices.getNowPrice(position.getStockCode());
        if(position.getOrderDirection().equals("买涨")){
            //判断亏损金额是否达到保证金金额
            BigDecimal negate = profit.negate();
            //如果买涨 signum 为-1则表示亏损
            if(signum == -1){
                //止损
                if(null != position.getStopTargetPrice() && nowPrice.compareTo(position.getStopTargetPrice()) <= 0){
                    //强制平仓
                    return liquidation = 1;
                }
                if (negate.compareTo(position.getOrderTotalPrice()) >= 0){//亏平强平
                    //强制平仓
                    return liquidation = -1;
                }
            }else{
                //止盈
                if(null != position.getProfitTargetPrice() && nowPrice.compareTo(position.getProfitTargetPrice()) >= 0){
                    //强制平仓
                    return liquidation = 2;
                }
            }
        }else{
            //买跌 signum
            if(signum == 1){
                //止损
                if(null != position.getStopTargetPrice() && nowPrice.compareTo(position.getStopTargetPrice()) >= 0){
                    //强制平仓
                    return liquidation = 1;
                }
                //判断亏损金额是否达到保证金金额
                if (profit.compareTo(position.getOrderTotalPrice()) >= 0){//亏平强平
                    //强制平仓
                    return liquidation = -1;
                }
            }else{
                //止盈
                if(null != position.getProfitTargetPrice() && nowPrice.compareTo(position.getProfitTargetPrice()) <= 0){
                    //强制平仓
                    return liquidation = 2;
                }
            }
        }
        return liquidation;
    }
    //平仓
    private void extracted(UserPosition position, BigDecimal nowPrice, Stock stock,Integer liquidation) {
        //-1强平 0未触发 1止损强平 2止盈强平
        BigDecimal sellOrderTotel = nowPrice.multiply(new BigDecimal(position.getOrderNum()));
        SiteSetting siteSetting = iSiteSettingService.getSiteSetting();
        // 手续费率
        BigDecimal xsPrice = sellOrderTotel.multiply(siteSetting.getForceStopFee());//手续费
        // 更新订单信息
        position.setSellOrderId(GeneratePosition.getPositionId());
        position.setSellOrderPrice(nowPrice);
        position.setSellOrderTime(new Date());
        userPositionMapper.updateById(position);
        if(liquidation == -1){
            userAssetsServices.availablebalanceChange(stock.getStockType(),
                    position.getUserId(),
                    EUserAssets.CONSTRAINT_CLOSE_POSITION,
                    position.getOrderTotalPrice(), "", "");
        }else if(liquidation == 1 || liquidation == 2){
            userAssetsServices.availablebalanceChange(stock.getStockType(),
                    position.getUserId(), EUserAssets.HANDLING_CHARGE,
                    xsPrice, "", "");
            PositionProfitVO profitVO = UserPointUtil.getPositionProfitVO(position, priceServices.getNowPrice(position.getStockCode()));
            userAssetsServices.availablebalanceChange(stock.getStockType(), position.getUserId(), EUserAssets.CLOSE_POSITION,
                    profitVO.getAllProfitAndLose(), "", "");
        }
        log.info("强制平仓成功,订单id: {}", position.getId());
    }
}
src/main/java/com/nq/service/impl/UserServiceImpl.java
@@ -13,6 +13,7 @@
import com.nq.pojo.*;
import com.nq.pojo.reponse.RUserAssets;
import com.nq.service.*;
import com.nq.utils.UserPointUtil;
import com.nq.utils.timeutil.DateTimeUtil;
import com.nq.utils.PropertiesUtil;
import com.nq.utils.SymmetricCryptoUtil;
@@ -27,6 +28,7 @@
import com.nq.vo.indexposition.IndexPositionVO;
import com.nq.vo.position.PositionProfitVO;
import com.nq.vo.position.PositionVO;
import com.nq.vo.position.UserPositionVO;
import com.nq.vo.stock.StockListVO;
import com.nq.vo.user.UserInfoVO;
@@ -117,8 +119,14 @@
    @Autowired
    ISiteMessageService iSiteMessageService;
    @Autowired
    private UserPositionMapper userPositionMapper;
    @Autowired
    IPriceServices priceServices;
    @Resource
    ApplyLeverMapper applyLeverMapper;
@@ -286,9 +294,30 @@
        String userJson = RedisShardedPoolUtils.get(loginToken);
        User user = (User) JsonUtil.string2Obj(userJson, User.class);
        User dbuser = this.userMapper.selectById(user.getId());
        SiteSetting siteSetting = iSiteSettingService.getSiteSetting();
        UserInfoVO userInfoVO = assembleUserInfoVO(dbuser, siteSetting);
        ApplyLever applyLever = applyLeverMapper.selectOne(new LambdaQueryWrapper<ApplyLever>()
                .eq(ApplyLever::getUserId, user.getId())
                .eq(ApplyLever::getState, 1)
                .orderByDesc(ApplyLever::getCreateTime)
                .last(" limit 1"));
        if(null == applyLever || applyLever.getLever().equals("1")){
            userInfoVO.setSiteLever("1");
        }else{
            userInfoVO.setSiteLever(leverSplit(applyLever.getLever()));
        }
        return ServerResponse.createBySuccess(userInfoVO);
    }
    public String leverSplit(String lever){
        String levers = "1/2/5/10";
        String[] parts = levers.split("/");
        int index = Arrays.asList(parts).indexOf(lever);
        if (index != -1) {
            return String.join("/", Arrays.copyOfRange(parts, 0, index + 1));
        }
        return null;
    }
@@ -484,19 +513,20 @@
            rUserAssets.setCumulativeProfitAndLoss(hProfitAndLose.toString());
            rUserAssets.setHandlingCharge(hMoney.toString());
            rUserAssets.setProfitAndLoss(profitAndLose.toString());
            rUserAssets.setIsZf(userAssets.getIsZf());
            rUserAssets.setAmountToBeCovered(userAssets.getAmountToBeCovered().toString());
            BigDecimal rate = rateServices.currencyRate(
                    EStockType.getEStockTypeByCode(userAssets.getAccectType()),EStockType.US);
           BigDecimal  availableBalanceUSD = amt;
           if(amt.compareTo(BigDecimal.ZERO)>0){
               availableBalanceUSD = amt.multiply(rate);
           }
            BigDecimal  availableBalanceUSD = amt;
            if(amt.compareTo(BigDecimal.ZERO)>0){
                availableBalanceUSD = amt.multiply(rate);
            }
            BigDecimal  freezeMoneyUSD = freeMoney;
           if(freeMoney.compareTo(BigDecimal.ZERO)>0){
               freezeMoneyUSD  = freeMoney.multiply(rate);
           }
            if(freeMoney.compareTo(BigDecimal.ZERO)>0){
                freezeMoneyUSD  = freeMoney.multiply(rate);
            }
            BigDecimal  totleMoneyUSD = totalAssets;
            if(totalAssets.compareTo(BigDecimal.ZERO)>0){
@@ -527,7 +557,9 @@
            rUserAssets.setCumulativeProfitAndLossUSD(cumulativeProfitAndLossUSD.setScale(s,BigDecimal.ROUND_UP).toString());
            rUserAssets.setHandlingChargeUSD(handlingChargeUSD.setScale(s,BigDecimal.ROUND_UP).toString());
            rUserAssets.setProfitAndLossUSD(profitAndLossUSD.setScale(s,BigDecimal.ROUND_UP).toString());
            rUserAssets.setProfitAndLoss(getProfitAndLose(userId,userAssets.getAccectType()).toString());
            BigDecimal decimal = new BigDecimal(rUserAssets.getTotalMoney()).add(new BigDecimal(rUserAssets.getProfitAndLoss()));
            rUserAssets.setTotalMoney(decimal.toString());
            AllProfitAndLose = AllProfitAndLose.add(profitAndLossUSD);
            allTotalAssets = allTotalAssets.add(totleMoneyUSD);
            allAmt = allAmt.add(availableBalanceUSD);
@@ -566,6 +598,28 @@
        return ServerResponse.createBySuccess(rUserAssetsList);
    }
    public BigDecimal getProfitAndLose(Integer userId,String  accectType){
        List<UserPosition> userPositions;
        userPositions = userPositionMapper.
                findMyPositionByCodeAndSpell(userId,
                        "","",
                        0, accectType);
        List<UserPositionVO> userPositionVOS = Lists.newArrayList();
        if (userPositions.size() > 0) {
            for (UserPosition position : userPositions) {
                UserPositionVO userPositionVO = UserPointUtil.assembleUserPositionVO(position, priceServices.getNowPrice(position.getStockCode()));
                userPositionVOS.add(userPositionVO);
            }
        }
        BigDecimal profitAndLose = BigDecimal.ZERO;
        for (UserPositionVO f : userPositionVOS) {
            profitAndLose = profitAndLose.add(f.getProfitAndLose());
        }
        return profitAndLose;
    }
    @Override
    public ServerResponse transfer(String fromType, String toType, String amt,HttpServletRequest request) {
        User user =  userService.getCurrentUser(request);
src/main/java/com/nq/service/impl/UserStockSubscribeServiceImpl.java
@@ -1,13 +1,17 @@
package com.nq.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.nq.common.ServerResponse;
import com.nq.dao.StockMapper;
import com.nq.dao.StockSubscribeMapper;
import com.nq.dao.UserMapper;
import com.nq.dao.UserStockSubscribeMapper;
import com.nq.enums.EStockType;
import com.nq.enums.EUserAssets;
import com.nq.pojo.*;
import com.nq.service.*;
import com.nq.utils.timeutil.DateTimeUtil;
@@ -59,6 +63,10 @@
    ISiteSettingService iSiteSettingService;
    @Autowired
    TradingHourServiceImpl tradingHourService;
    @Resource
    IUserAssetsServices iUserAssetsServices;
    @Autowired
    StockMapper stockMapper;
    /**
     * 用户新股申购
     * @param model
@@ -81,14 +89,8 @@
                if (siteProduct.getRealNameDisplay() && (StringUtils.isBlank(user.getRealName()) || StringUtils.isBlank(user.getIdCard()))) {
                    return ServerResponse.createByErrorMsg("订单失败,请先实名认证",request);
                }
//                //判断休息日不能买入
//                if (siteProduct.getHolidayDisplay()) {
//                    return ServerResponse.createByErrorMsg("No trading on weekends or holidays!");
//                }
                //判断股票是否在可交易时间段
                Boolean b = tradingHourService.timeCheck();
                if (b) {
                    return ServerResponse.createByErrorMsg("订单失败,不在股票交易时段",request);
                if(new Date().before(stockSubscribe.getSubscribeTime())){
                    return ServerResponse.createByErrorMsg("未到申购时间",request);
                }
                //重复申购限制
                UserStockSubscribe userStockSubscribe = userStockSubscribeMapper.selectOne(new QueryWrapper<UserStockSubscribe>().eq("new_code", model.getNewCode()).eq("user_id", user.getId()));
@@ -183,23 +185,7 @@
                    siteMessage.setAddTime(DateTimeUtil.getCurrentDate());
                    if (stockSubscribe.getType() == 2){
                        User user = userMapper.selectById(userStockSubscribe.getUserId());
                        UserStockSubscribe userStockSubscribe1 = userStockSubscribeMapper.load(model.getId());
                        int refundenum = userStockSubscribe1.getApplyNums() - model.getApplyNumber();
//                        log.info("refundenum"+refundenum);
                        Integer refund =refundenum * stockSubscribe.getPrice().intValue();
//                        log.info("退还金额"+refund);
                       int ret1 = userMapper.updateByPrimaryKey(user);
                       if (ret1 <= 0) {
                                return ServerResponse.createByErrorMsg("Application failed due to unknown reasons");
                            }
                        siteMessage.setContent("【新股申购中签】恭喜您,新股申购中签成功,申购金额:"+ userStockSubscribe.getBond() +"退还"+refund+",请及时关注哦。");
                    }else {
                        siteMessage.setContent("【新股申购中签】恭喜您,新股申购中签成功,申购金额:" + userStockSubscribe.getBond() + ",请及时关注哦。");
                    }
                    siteMessage.setContent("【新股申购中签】恭喜您,新股申购中签成功,申购金额:"+ userStockSubscribe.getBond() );
                    iSiteMessageService.insert(siteMessage);
                }else
                if(ret>0 && model.getStatus() == 2) {
@@ -367,39 +353,39 @@
                return ServerResponse.createByErrorMsg("参数错误",request);
            }
            UserStockSubscribe userStockSubscribe = userStockSubscribeMapper.load(id);
            log.info("userStockSubscribe:{}",userStockSubscribe);
            if (userStockSubscribe != null && userStockSubscribe.getUserId().equals(user.getId())) {
                StockSubscribe stockSubscribe = stockSubscribeMapper.selectOne(new QueryWrapper<>(new StockSubscribe()).eq("code", userStockSubscribe.getNewCode()));
                if(userStockSubscribe.getType()== 2 ){
                StockSubscribe stockSubscribe = stockSubscribeMapper.selectOne(new QueryWrapper<>(new StockSubscribe())
                        .eq("code", userStockSubscribe.getNewCode()));
                if(userStockSubscribe.getStatus()== 2 ){
                    return ServerResponse.createByErrorMsg("未中签,无需支付",request);
                }
                //判断时间
                if (stockSubscribe.getSubscriptionTime().getTime() < System.currentTimeMillis()) {
                    return ServerResponse.createByErrorMsg("不在认缴时间之内",request);
                if(null == stockSubscribe){
                    return  ServerResponse.createByErrorMsg("新股不存在",request);
                }
                Stock stock = stockMapper.selectOne(new LambdaQueryWrapper<Stock>().eq(Stock::getStockCode, stockSubscribe.getCode()));
                if(null == stock){
                    return  ServerResponse.createByErrorMsg("股票不存在",request);
                }
                if (userStockSubscribe.getStatus() == 3) {
                    userStockSubscribe.setSubmitTime(DateTimeUtil.getCurrentDate());
                    userStockSubscribe.setStatus(4);
                    BigDecimal bigDecimal =  iUserAssetsServices.
                            getAvailableBalance(stock.getStockType(),
                                    userStockSubscribe.getUserId());
                    User user1 = userMapper.selectById(userStockSubscribe.getUserId());
                    ret = userMapper.updateById(user1);
                }
                else {
                    BigDecimal multiply = userStockSubscribe.getBuyPrice().multiply(new BigDecimal(userStockSubscribe.getApplyNumber()));
                    if(bigDecimal.compareTo(multiply) < 0){
                        return ServerResponse.createByErrorMsg("余额不足",request);
                    }
                    iUserAssetsServices.availablebalanceChange(stock.getStockType(),userStockSubscribe.getUserId(),
                            EUserAssets.BUY,multiply.negate(),"","");
                    userStockSubscribeMapper.update1(userStockSubscribe);
                    return  ServerResponse.createBySuccess();
                } else {
                    return ServerResponse.createByErrorMsg("不成功的申请者不收取任何费用",request);
                }
            } else {
                return ServerResponse.createByErrorMsg("新股认购订单不存在!",request);
            }
            if (ret > 0) {
                ret = userStockSubscribeMapper.update1(userStockSubscribe);
                if (ret > 0) {
                    return ServerResponse.createBySuccessMsg("成功操作",request);
                } else {
                    return ServerResponse.createByErrorMsg("失败操作",request);
                }
            }else {
                return ServerResponse.createByErrorMsg("扣除失败",request);
            }
        }
        return ServerResponse.createByErrorMsg("请先登录",request);
src/main/java/com/nq/utils/task/stock/StockTask.java
@@ -1,15 +1,23 @@
package com.nq.utils.task.stock;
import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.google.gson.Gson;
import com.nq.common.ServerResponse;
import com.nq.dao.*;
import com.nq.enums.EStockType;
import com.nq.pojo.*;
import com.nq.service.IMandatoryLiquidationService;
import com.nq.service.IStockService;
import com.nq.service.IUserAssetsServices;
import com.nq.service.IUserPositionService;
import com.nq.utils.http.HttpClientRequest;
import com.nq.utils.redis.RedisKeyUtil;
import com.nq.utils.redis.RedisShardedPoolUtils;
import com.nq.utils.stock.BuyAndSellUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -21,6 +29,9 @@
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Collectors;
@Component
@@ -30,10 +41,34 @@
    @Autowired
    StockMapper stockMapper;
    @Autowired
    IUserPositionService userPositionService;
    @Autowired
    UserPositionMapper userPositionMapper;
    @Autowired
    IMandatoryLiquidationService mandatoryLiquidationService;
    @Autowired
    UserStockSubscribeMapper userStockSubscribeMapper;
    @Autowired
    StockSubscribeMapper stockSubscribeMapper;
    @Autowired
    IUserPositionService iUserPositionService;
    @Autowired
    IUserAssetsServices userAssetsServices;
    private final Lock ballotLock = new ReentrantLock();
    private final Lock subscriptionLock = new ReentrantLock();
    private final Lock stockConstraintLock = new ReentrantLock();
    private static final Logger log = LoggerFactory.getLogger(StockTask.class);
@@ -42,9 +77,8 @@
    /**
     * 同步系统所需要的股票
     * */
    @Scheduled(cron = "0 0/1 *  * * ?")
    @Scheduled(cron = "0 0 0/2  * * ?")
    public void syncINStockData() {
        loadAllStock(EStockType.US);
        loadAllStock(EStockType.IN);
//        loadAllStock(EStockType.HK);
    }
@@ -55,10 +89,10 @@
    /**
     * 同步美国股票
     * */
//    @Scheduled(cron = "0 0/3 * * * ?")
//    public  void loadStockCompanies(){
//        loadAllCompanies();
//    }
//    @Scheduled(cron = "0 0/30 * * * ?")
    public  void loadStockCompanies(){
        loadAllCompanies();
    }
@@ -147,4 +181,87 @@
            log.error("同步出错", e);
        }
    }
    @Scheduled(cron = "0 0/10 * * * ?")
    public void ballot() {
        if (ballotLock.tryLock()) {
            try {
                log.info("新股上市转持仓定时任务--------->开始");
                List<StockSubscribe> stockSubscribes = stockSubscribeMapper.selectList(new LambdaQueryWrapper<StockSubscribe>()
                        .lt(StockSubscribe::getListDate, DateUtil.date()));
                if (CollectionUtils.isNotEmpty(stockSubscribes)) {
                    List<String> codeList = stockSubscribes.stream().map(StockSubscribe::getCode).collect(Collectors.toList());
                    List<UserStockSubscribe> userStockSubscribes = userStockSubscribeMapper.selectList(new LambdaQueryWrapper<UserStockSubscribe>()
                            .eq(UserStockSubscribe::getStatus, 4).in(UserStockSubscribe::getNewCode, codeList));
                    //订单转持仓
                    userStockSubscribes.forEach(f -> {
                        ServerResponse serverResponse = iUserPositionService.newStockToPosition(f.getId());//转持仓
                        if(serverResponse.isSuccess()){
                            f.setStatus(5);
                            userStockSubscribeMapper.updateById(f);
                        }else{
                            log.info("新股上市转持仓失败申购订单id:"+f.getId()+",失败原因:"+serverResponse.getMsg());
                        }
                    });
                }
                log.info("新股上市转持仓定时任务--------->结束");
            } catch (Exception e) {
                log.error("新股上市转持仓定时任务发生异常", e);
            } finally {
                ballotLock.unlock();
            }
        } else {
            log.info("新股上市转持仓定时任务--------->上次任务还未执行完成,本次任务忽略");
        }
    }
//    @Scheduled(cron = "0/5 * * * * ?")
//    public void subscription() {
//        if (subscriptionLock.tryLock()) {
//            try {
//                log.info("自动转已认缴--------->开始");
//                List<UserStockSubscribe> userStockSubscribes = userStockSubscribeMapper.selectList(new LambdaQueryWrapper<UserStockSubscribe>()
//                        .eq(UserStockSubscribe::getStatus, 3));
//                userStockSubscribes.forEach(f->{
//                    Stock stock = stockMapper.selectOne(new LambdaQueryWrapper<Stock>().eq(Stock::getStockCode, f.getNewCode()));
//                    UserAssets userAssets = userAssetsServices.assetsByTypeAndUserId(stock.getStockType(),f.getUserId());
//                    if(null != userAssets && userAssets.getAmountToBeCovered().compareTo(BigDecimal.ZERO) == 0){
//                        f.setStatus(4);
//                        userStockSubscribeMapper.updateById(f);
//                    }
//                });
//                log.info("自动转已认缴--------->结束");
//            } catch (Exception e) {
//                log.error("自动转已认缴定时任务发生异常", e);
//            } finally {
//                subscriptionLock.unlock();
//            }
//        } else {
//            log.info("自动转已认缴定时任务--------->上次任务还未执行完成,本次任务忽略");
//        }
//    }
    /**
     * 强制平仓
     */
    @Scheduled(cron = "0/1 * * * * ?")
    public void stockConstraint(){
        if (stockConstraintLock.tryLock()) {
            log.info("强制平仓任务:--------->开始");
            try {
                List<UserPosition> userPositions = userPositionMapper.selectList(new LambdaQueryWrapper<UserPosition>().isNull(UserPosition::getSellOrderId));
                if(CollectionUtils.isNotEmpty(userPositions)){
                    userPositionService.stockConstraint(userPositions);
                }
            } catch (Exception e) {
                e.printStackTrace();
                log.error("强制平仓任务错误:" + e.getMessage());
            } finally {
                stockConstraintLock.unlock();
                log.info("强制平仓任务:--------->结束");
            }
        } else {
            log.info("强制平仓任务--------->上次任务还未执行完成,本次任务忽略");
        }
    }
}