package com.nq.service.impl; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageInfo; import com.nq.common.ResponseCode; import com.nq.common.ServerResponse; import com.nq.dao.StockAiMapper; import com.nq.dao.StockAiOrderMapper; import com.nq.dao.StockAiOrderPositionMapper; 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; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.servlet.http.HttpServletRequest; import java.math.BigDecimal; import java.util.Date; import java.util.List; import java.util.concurrent.ConcurrentHashMap; @Service("iStockAiService") public class StockAiServiceImpl implements IStockAiService { private static final Logger log = LoggerFactory.getLogger(StockAiServiceImpl.class); private final ConcurrentHashMap locks = new ConcurrentHashMap<>(); @Autowired StockAiMapper stockAiMapper; @Autowired StockAiOrderMapper stockAiOrderMapper; @Autowired StockAiOrderPositionMapper stockAiOrderPositionMapper; @Autowired ISiteProductService iSiteProductService; @Autowired IUserService iUserService; @Autowired IUserAssetsServices iUserAssetsServices; @Autowired private UserAssetsServices userAssetsServices; /** * 获取上架ai产品 * @param pageNum * @param pageSize * @return */ @Override public ServerResponse getStockAiList(Integer pageNum, Integer pageSize, String stockName) { try { PageHelper.startPage(pageNum, pageSize); List stockAiList = stockAiMapper.selectList(new QueryWrapper() .eq("status", EStockAIStatus.online.getValue()) .eq(StringUtils.isNotBlank(stockName),"stock_name", stockName)); // 获取分页信息 PageInfo pageInfo = new PageInfo<>(stockAiList); return ServerResponse.createBySuccess(pageInfo); } catch (Exception ex) { log.error("StockAiService getStockAiList error", ex); } return ServerResponse.createByError(); } /** * 购买ai产品 * @param id * @param buyNum * @return */ @Override @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(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("订单失败,请先实名认证", request); } if (siteProduct.getRealNameDisplay() && user.getIsLock().intValue() == 1) { return ServerResponse.createByErrorMsg("订单失败,帐户已被锁定", request); } StockAI stockAI = stockAiMapper.selectById(id); if (stockAI == null) { return ServerResponse.createByErrorMsg("订单失败,AI股票不存在", request); } if (!stockAI.getStatus().equals(EStockAIStatus.online.getValue())) { return ServerResponse.createByErrorMsg("订单失败,AI股票已下架", request); } if(buyNum.compareTo(stockAI.getMinPrice()) < 0){ return ServerResponse.createByErrorMsg("最低购买数量" + stockAI.getMinPrice(), request); } //获取用户账户 UserAssets userAssets = iUserAssetsServices.assetsByTypeAndUserId(stockAI.getStockType(), user.getId()); /*BigDecimal finalBuyNum = buyNum; //如果不是默认货币需要转换金额 if (!stockAI.getStockType().equals(EStockType.getDefault().getCode())) { buyNum = userAssetsServices.exchangeAmountByRate(stockAI.getStockType(), buyNum); }*/ if(buyNum.compareTo(userAssets.getAvailableBalance()) > 0){ return ServerResponse.createByErrorMsg("可用余额不足" + userAssets.getAvailableBalance(), request); } if(userAssets.getAmountToBeCovered().compareTo(BigDecimal.ZERO) > 0){ return ServerResponse.createByErrorMsg("请先缴清待补资金", request); } iUserAssetsServices.aiAvailableBalanceChange(stockAI.getStockType(), user.getId(), EUserAssets.BUY_AI, buyNum); StockAIOrder stockAIOrder = new StockAIOrder(); stockAIOrder.setUserId(user.getId()); stockAIOrder.setStockAiId(id.intValue()); stockAIOrder.setBuyDate(new Date()); stockAIOrder.setBuyAmount(buyNum); stockAIOrder.setRemainAmount(buyNum); stockAIOrder.setRealEarning(BigDecimal.valueOf(0)); stockAIOrder.setStatus(EStockAIOrderStatus.wait.getStatus()); //等待审核 stockAiOrderMapper.insert(stockAIOrder); return ServerResponse.createBySuccessMsg("下单成功", request); } } catch (Exception e) { log.error("StockAiService buyStockAiList {}", e.getMessage()); } return ServerResponse.createByError(); } /** * 获取ai产品订单 * @param pageNum * @param pageSize * @param status * @param request * @return */ @Override public ServerResponse getStockAiOrderList(Integer pageNum, Integer pageSize, String status, HttpServletRequest request) { try { User user = iUserService.getCurrentUser(request); if (user == null ){ return ServerResponse.createByErrorCodeMsg(ResponseCode.NEED_LOGIN.getCode(),"请先登录", request); } PageHelper.startPage(pageNum, pageSize); List stockAIOrders = stockAiOrderMapper.getStockAiOrderList(user.getId(), status); // 获取分页信息 PageInfo pageInfo = new PageInfo<>(stockAIOrders); return ServerResponse.createBySuccess(pageInfo); } catch (Exception e) { log.error("StockAiService getStockAiOrderList error", e); } return ServerResponse.createByError(); } @Override public ServerResponse getAdminStockAiList(Integer pageNum, Integer pageSize, String stockType, String status, String name) { try { PageHelper.startPage(pageNum, pageSize); List stockAiList = stockAiMapper.getStockAiList(stockType, status, name); // 获取分页信息 PageInfo pageInfo = new PageInfo<>(stockAiList); if (!pageInfo.getList().isEmpty()) { List newStockAiList = pageInfo.getList(); 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); } return ServerResponse.createByError(); } /** * 新增或修改 * @param model * @return */ @Override public ServerResponse editStockAi(StockAI model) { try { if (model == null) { return ServerResponse.createByErrorMsg("editStockAi model is null"); } if (StringUtils.isBlank(model.getStockType()) || StringUtils.isBlank(model.getStockName()) || model.getMinPrice() == null || model.getSuccessRate() == null || model.getExpectedEarning() == null || StringUtils.isBlank(model.getStatus())) { return ServerResponse.createByErrorMsg("请完善必填信息"); } if (!EStockType.isExistByCode(model.getStockType())) { return ServerResponse.createByErrorMsg("股票市场不存在"); } //新增 if (model.getId() == null) { //查询是否存在 StockAI stockAI = stockAiMapper.selectOne(new QueryWrapper().eq("stock_name", model.getStockName())); if (stockAI != null) { return ServerResponse.createByErrorMsg("当前股票已添加"); } model.setCreateDate(new Date()); stockAiMapper.insert(model); } else { //修改 stockAiMapper.updateById(model); } return ServerResponse.createBySuccess("操作成功"); } catch (Exception e) { e.printStackTrace(); log.error(e.getMessage(), e); } return ServerResponse.createByError(); } /** * 后台查询ai交易订单 * @param pageNum * @param pageSize * @param stockType * @param status * @param userId * @param phone * @return */ @Override public ServerResponse getAdminStockAiOrderList(Integer pageNum, Integer pageSize, String stockType, String status, Integer userId, String phone) { try { PageHelper.startPage(pageNum, pageSize); List stockAIOrders = stockAiOrderMapper.getAdminStockAiOrderList(stockType, status, userId, phone); // 获取分页信息 PageInfo pageInfo = new PageInfo<>(stockAIOrders); if (!pageInfo.getList().isEmpty()) { List newStockAiOrders = pageInfo.getList(); newStockAiOrders.forEach(stockAiOrderVO -> { EStockType eStockType = EStockType.getEStockTypeByCode(stockAiOrderVO.getStockType()); stockAiOrderVO.setStockTypeName(eStockType.getSymbol1()); stockAiOrderVO.setSymbol(stockType); }); pageInfo.setList(newStockAiOrders); } return ServerResponse.createBySuccess(pageInfo); } catch (Exception e) { log.error("StockAiService getAdminStockAiOrderList error", e); } return ServerResponse.createByError(); } /** * 建仓 * @param model * @return */ @Override public ServerResponse openPosition(StockAIOrderPosition model) { try { Object lock = locks.computeIfAbsent(Long.valueOf(model.getStockAiOrderId()), k -> new Object()); synchronized (lock) { StockAIOrder stockAIOrder = stockAiOrderMapper.selectById(model.getStockAiOrderId()); if (stockAIOrder == null) { return ServerResponse.createByErrorMsg("AI订单不存在"); } if (!stockAIOrder.getStatus().equals(EStockAIOrderStatus.passed.getStatus())) { return ServerResponse.createByErrorMsg("申请通过状态才能建仓!"); } //计算剩余金额 BigDecimal remainAmount = model.getStockPrice().multiply(BigDecimal.valueOf(model.getStockNum())); if (stockAIOrder.getRemainAmount().compareTo(remainAmount) < 0) { return ServerResponse.createByErrorMsg("剩余买入金额不足"); } stockAIOrder.setRemainAmount(stockAIOrder.getRemainAmount().subtract(remainAmount)); //计算收益 (平仓-建仓)*数量 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)); //保存 stockAiOrderMapper.updateById(stockAIOrder); stockAiOrderPositionMapper.insert(model); return ServerResponse.createBySuccess("建仓成功"); } } catch (Exception e) { log.error("StockAiService openPosition error", e); } return ServerResponse.createByError(); } @Override @Transactional(rollbackFor = Exception.class) public ServerResponse orderOperation(Long id, String status) { try { Object lock = locks.computeIfAbsent(id, k -> new Object()); synchronized (lock) { StockAIOrder stockAIOrder = stockAiOrderMapper.selectById(id); if (stockAIOrder == null) { return ServerResponse.createByErrorMsg("AI订单不存在"); } if (status.equals(EStockAIOrderStatus.passed.getStatus())) { //通过 if (!stockAIOrder.getStatus().equals(EStockAIOrderStatus.wait.getStatus())) { return ServerResponse.createByErrorMsg("只能通过待审核订单"); } } else if (status.equals(EStockAIOrderStatus.notPass.getStatus())) { if (!stockAIOrder.getStatus().equals(EStockAIOrderStatus.wait.getStatus())) { return ServerResponse.createByErrorMsg("只能拒绝待审核订单"); } //拒绝TODO 归还买入金额 StockAI stockAI = stockAiMapper.selectById(stockAIOrder.getStockAiId()); //买入金额 BigDecimal buyNum = stockAIOrder.getBuyAmount(); 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 stockAIOrderPositionList = stockAiOrderPositionMapper .selectList(new QueryWrapper() .eq("stock_ai_order_id", id)); //结算金额 BigDecimal amount = stockAIOrder.getBuyAmount(); if (!stockAIOrderPositionList.isEmpty()) { //总收益 BigDecimal earningsSUM = stockAIOrderPositionList.stream() .map(StockAIOrderPosition::getEarnings) // 获取 BigDecimal 字段 .filter(Objects::nonNull) // 过滤 null 值 .reduce(BigDecimal.ZERO, BigDecimal::add); // 累加 amount = amount.add(earningsSUM); }*/ StockAI stockAI = stockAiMapper.selectById(stockAIOrder.getStockAiId()); //结算修改为平仓状态 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()); stockAiOrderMapper.updateById(stockAIOrder); return ServerResponse.createBySuccess("操作成功"); } } catch (Exception 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 positionVOList = stockAiOrderPositionMapper.getPositionListByOrderId(stockAiOrderId); PageInfo pageInfo = new PageInfo<>(positionVOList); return ServerResponse.createBySuccess(pageInfo); } catch (Exception e) { log.error("StockAiService getPositionList error", e); } return ServerResponse.createByError(); } }