zyy
2025-07-21 f25b39e0d5fcae415a8824fc03d42fe681e96bf8
src/main/java/com/nq/service/impl/StockAiServiceImpl.java
@@ -3,7 +3,7 @@
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.nq.Repository.ExchangeRateRepository;
import com.nq.common.ResponseCode;
import com.nq.common.ServerResponse;
import com.nq.dao.StockAiMapper;
import com.nq.dao.StockAiOrderMapper;
@@ -11,6 +11,7 @@
import com.nq.enums.*;
import com.nq.pojo.*;
import com.nq.service.*;
import com.nq.vo.stock.ai.StockAIOrderPositionVO;
import com.nq.vo.stock.ai.StockAiOrderTypeVO;
import com.nq.vo.stock.ai.StockAiOrderVO;
import com.nq.vo.stock.ai.StockAiVO;
@@ -24,7 +25,6 @@
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
@Service("iStockAiService")
@@ -45,7 +45,7 @@
    @Autowired
    IUserAssetsServices iUserAssetsServices;
    @Autowired
    ExchangeRateRepository exchangeRateRepository;
    private UserAssetsServices userAssetsServices;
    /**
     * 获取上架ai产品
@@ -75,71 +75,60 @@
     * @return
     */
    @Override
    @Transactional
    @Transactional(rollbackFor = Exception.class)
    public ServerResponse buyStockAi(Long id, BigDecimal buyNum, HttpServletRequest request) {
        try {
            User user = iUserService.getCurrentUser(request);
            if (user == null ){
                return ServerResponse.createByErrorCodeMsg(401,"请先登录");
                return ServerResponse.createByErrorCodeMsg(ResponseCode.NEED_LOGIN.getCode(),"请先登录", request);
            }
            Object lock = locks.computeIfAbsent(Long.valueOf(user.getId()), k -> new Object());
            synchronized (lock){
                SiteProduct siteProduct = iSiteProductService.getProductSetting();
                if (siteProduct.getRealNameDisplay() && user.getIsActive() != 2) {
                    return ServerResponse.createByErrorMsg("订单失败,请先实名认证");
                    return ServerResponse.createByErrorMsg("订单失败,请先实名认证", request);
                }
                if (siteProduct.getRealNameDisplay() && user.getIsLock().intValue() == 1) {
                    return ServerResponse.createByErrorMsg("订单失败,帐户已被锁定");
                    return ServerResponse.createByErrorMsg("订单失败,帐户已被锁定", request);
                }
                StockAI stockAI = stockAiMapper.selectById(id);
                if (stockAI == null) {
                    return ServerResponse.createByErrorMsg("订单失败,AI股票不存在");
                    return ServerResponse.createByErrorMsg("订单失败,AI股票不存在", request);
                }
                if (!stockAI.getStatus().equals(EStockAIStatus.online.getValue())) {
                    return ServerResponse.createByErrorMsg("订单失败,AI股票已下架");
                    return ServerResponse.createByErrorMsg("订单失败,AI股票已下架", request);
                }
                if(buyNum.compareTo(stockAI.getMinPrice()) < 0){
                    return ServerResponse.createByErrorMsg("最低购买数量" + stockAI.getMinPrice());
                    return ServerResponse.createByErrorMsg("最低购买数量" + stockAI.getMinPrice(), request);
                }
                //获取用户账户
                UserAssets userAssets = iUserAssetsServices.assetsByTypeAndUserId(EStockType.MX.getCode(), user.getId());
                /*BigDecimal finalBuyNum = buyNum;    //购买金额
                BigDecimal finalBuyNum = buyNum;
                //如果不是墨西哥币需要转换金额
                if (!stockAI.getStockType().equals(EStockType.MX.getCode())) {
                    EStockType stockType = EStockType.getEStockTypeByCode(stockAI.getStockType());
                    ExchangeRate exchangeRate = exchangeRateRepository.findExchangeRateByCurrencyAndConversionCurrency(stockType.getSymbol(), EStockType.MX.getSymbol())
                            .orElse(null);
                    if (exchangeRate == null) {
                        return ServerResponse.createByErrorMsg("当前货币汇率无法转换");
                    }
                    //转换为墨西哥币
                    buyNum = iUserAssetsServices.exchangeAmountByRate(buyNum, exchangeRate.getRata());
                }*/
                    buyNum = userAssetsServices.exchangeAmountByRate(stockAI.getStockType(), buyNum);
                }
                if(buyNum.compareTo(userAssets.getAvailableBalance()) > 0){
                    return ServerResponse.createByErrorMsg("可用余额不足" + userAssets.getAvailableBalance());
                    return ServerResponse.createByErrorMsg("可用余额不足" + userAssets.getAvailableBalance(), request);
                }
                if(userAssets.getAmountToBeCovered().compareTo(BigDecimal.ZERO) > 0){
                    return ServerResponse.createByErrorMsg("请先缴清待补资金");
                    return ServerResponse.createByErrorMsg("请先缴清待补资金", request);
                }
                Boolean flag = iUserAssetsServices.aiAvailableBalanceChange(stockAI.getStockType(), user.getId(), EUserAssets.BUY_AI, buyNum, null);
                if (!flag)  {
                    return ServerResponse.createByErrorMsg("扣款失败,无法转换货币");
                }
                //已经转化 直接穿MEX类型
                iUserAssetsServices.aiAvailableBalanceChange(EStockType.MX.getCode(), user.getId(), EUserAssets.BUY_AI, buyNum);
                StockAIOrder stockAIOrder = new StockAIOrder();
                stockAIOrder.setUserId(user.getId());
                stockAIOrder.setStockAiId(id);
                stockAIOrder.setStockAiId(id.intValue());
                stockAIOrder.setBuyDate(new Date());
                stockAIOrder.setBuyAmount(buyNum);
                stockAIOrder.setRemainAmount(buyNum);
                stockAIOrder.setBuyAmount(finalBuyNum);
                stockAIOrder.setRemainAmount(finalBuyNum);
                stockAIOrder.setRealEarning(BigDecimal.valueOf(0));
                stockAIOrder.setStatus(EStockAIOrderStatus.wait.getStatus());   //等待审核
                stockAiOrderMapper.insert(stockAIOrder);
                return ServerResponse.createBySuccessMsg("下单成功");
                return ServerResponse.createBySuccessMsg("下单成功", request);
            }
        } catch (Exception e) {
            log.error("StockAiService buyStockAiList  {}", e.getMessage());
@@ -160,7 +149,7 @@
        try {
            User user = iUserService.getCurrentUser(request);
            if (user == null ){
                return ServerResponse.createByErrorCodeMsg(401,"请先登录");
                return ServerResponse.createByErrorCodeMsg(ResponseCode.NEED_LOGIN.getCode(),"请先登录", request);
            }
            PageHelper.startPage(pageNum, pageSize);
            List<StockAiOrderTypeVO> stockAIOrders = stockAiOrderMapper.getStockAiOrderList(user.getId(), status);
@@ -183,15 +172,13 @@
            if (!pageInfo.getList().isEmpty()) {
                List<StockAiVO> newStockAiList = pageInfo.getList();
                newStockAiList.forEach(stockAiVO -> {
                pageInfo.getList().forEach(stockAiVO -> {
                    EStockType eStockType = EStockType.getEStockTypeByCode(stockAiVO.getStockType());
                    stockAiVO.setStockTypeName(eStockType.getSymbol1());
                    stockAiVO.setSymbol(stockType);
                });
                pageInfo.setList(newStockAiList);
            }
            return ServerResponse.createBySuccess(pageInfo);
        } catch (Exception ex) {
            log.error("StockAiService getAdminStockAiList error", ex);
@@ -231,6 +218,7 @@
            }
            return ServerResponse.createBySuccess("操作成功");
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage(), e);
        }
        return ServerResponse.createByError();
@@ -278,7 +266,7 @@
    @Override
    public ServerResponse openPosition(StockAIOrderPosition model) {
        try {
            Object lock = locks.computeIfAbsent(model.getStockAiOrderId(), k -> new Object());
            Object lock = locks.computeIfAbsent(Long.valueOf(model.getStockAiOrderId()), k -> new Object());
            synchronized (lock) {
                StockAIOrder stockAIOrder = stockAiOrderMapper.selectById(model.getStockAiOrderId());
                if (stockAIOrder == null) {
@@ -299,6 +287,7 @@
                BigDecimal earnings = model.getCoverPrice().subtract(model.getStockPrice()).multiply(BigDecimal.valueOf(model.getStockNum()));
                model.setCreatDate(new Date());
                model.setEarnings(earnings);
                model.setStatus(0);
                stockAIOrder.setRealEarning(stockAIOrder.getRealEarning().add(earnings));
                //保存
@@ -313,6 +302,7 @@
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ServerResponse orderOperation(Long id, String status) {
        try {
            Object lock = locks.computeIfAbsent(id, k -> new Object());
@@ -334,27 +324,14 @@
                    StockAI stockAI = stockAiMapper.selectById(stockAIOrder.getStockAiId());
                    //买入金额
                    BigDecimal buyNum =  stockAIOrder.getBuyAmount();
                    /*//如果不是墨西哥币需要转换金额
                    if (!stockAI.getStockType().equals(EStockType.MX.getCode())) {
                        EStockType stockType = EStockType.getEStockTypeByCode(stockAI.getStockType());
                        ExchangeRate exchangeRate = exchangeRateRepository.findExchangeRateByCurrencyAndConversionCurrency(stockType.getSymbol(), EStockType.MX.getSymbol())
                                .orElse(null);
                        if (exchangeRate == null) {
                            return ServerResponse.createByErrorMsg("请先设置当前货币汇率");
                        }
                        //转换为墨西哥币
                        buyNum = iUserAssetsServices.exchangeAmountByRate(buyNum, exchangeRate.getRata());
                    }*/
                    Boolean flag = iUserAssetsServices.aiAvailableBalanceChange(stockAI.getStockType(), stockAIOrder.getUserId(), EUserAssets.BUY_AI_REJECT, buyNum, null);
                    if (!flag)  {
                        return ServerResponse.createByErrorMsg("扣款失败,无法转换货币");
                    }
                    iUserAssetsServices.aiAvailableBalanceChange(stockAI.getStockType(), stockAIOrder.getUserId(), EUserAssets.BUY_AI_REJECT, buyNum);
                } else if (status.equals(EStockAIOrderStatus.finished.getStatus())) {
                    if (!stockAIOrder.getStatus().equals(EStockAIOrderStatus.passed.getStatus())) {
                        return ServerResponse.createByErrorMsg("只能结算申请通过订单");
                    }
                    //结算 TODO结算建仓 计算收益
                    /*//所有建仓
                    List<StockAIOrderPosition> stockAIOrderPositionList = stockAiOrderPositionMapper
                            .selectList(new QueryWrapper<StockAIOrderPosition>()
                                    .eq("stock_ai_order_id", id));
@@ -369,26 +346,12 @@
                        amount = amount.add(earningsSUM);
                    }*/
                    StockAI stockAI = stockAiMapper.selectById(stockAIOrder.getStockAiId());
                    //收益+本金
                    BigDecimal amount = stockAIOrder.getBuyAmount().add(stockAIOrder.getRealEarning());
                    //需要解冻金额
                    BigDecimal buyAmount = stockAIOrder.getBuyAmount();
                    /*//如果不是墨西哥币需要转换金额
                    if (!stockAI.getStockType().equals(EStockType.MX.getCode())) {
                        EStockType stockType = EStockType.getEStockTypeByCode(stockAI.getStockType());
                        ExchangeRate exchangeRate = exchangeRateRepository.findExchangeRateByCurrencyAndConversionCurrency(stockType.getSymbol(), EStockType.MX.getSymbol())
                                .orElse(null);
                        if (exchangeRate == null) {
                            return ServerResponse.createByErrorMsg("请先设置当前货币汇率");
                        }
                        //转换为墨西哥币
                        amount = iUserAssetsServices.exchangeAmountByRate(amount, exchangeRate.getRata());
                        buyAmount = iUserAssetsServices.exchangeAmountByRate(buyAmount, exchangeRate.getRata());
                    }*/
                    Boolean flag = iUserAssetsServices.aiAvailableBalanceChange(stockAI.getStockType(), stockAIOrder.getUserId(), EUserAssets.AI_SETTLEMENT, amount, buyAmount);
                    if (!flag)  {
                        return ServerResponse.createByErrorMsg("扣款失败,无法转换货币");
                    }
                    //结算修改为平仓状态
                    stockAiOrderPositionMapper.updateStatusByOrderId(stockAIOrder.getId(), 1);
                    //归还本金
                    iUserAssetsServices.aiAvailableBalanceChange(stockAI.getStockType(), stockAIOrder.getUserId(), EUserAssets.AI_SETTLEMENT, stockAIOrder.getBuyAmount());
                    //收益
                    iUserAssetsServices.aiAvailableBalanceChange(stockAI.getStockType(), stockAIOrder.getUserId(), EUserAssets.AI_SETTLEMENT_INT, stockAIOrder.getRealEarning());
                }
                stockAIOrder.setStatus(status);
                stockAIOrder.setAuditDate(new Date());
@@ -396,7 +359,27 @@
                return ServerResponse.createBySuccess("操作成功");
            }
        } catch (Exception e) {
            log.error("StockAiService openPosition error", e);
            log.error("StockAiService orderOperation error", e);
        }
        return ServerResponse.createByError();
    }
    /**
     * 建仓列表
     * @param pageNum
     * @param pageSize
     * @param stockAiOrderId
     * @return
     */
    @Override
    public ServerResponse getPositionList(Integer pageNum, Integer pageSize, Integer stockAiOrderId) {
        try {
            PageHelper.startPage(pageNum, pageSize);
            List<StockAIOrderPositionVO> positionVOList = stockAiOrderPositionMapper.getPositionListByOrderId(stockAiOrderId);
            PageInfo<StockAIOrderPositionVO> pageInfo = new PageInfo<>(positionVOList);
            return ServerResponse.createBySuccess(pageInfo);
        } catch (Exception e) {
            log.error("StockAiService getPositionList error", e);
        }
        return ServerResponse.createByError();
    }