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.Repository.ExchangeRateRepository;
|
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.StockAiOrderTypeVO;
|
import com.nq.vo.stock.ai.StockAiOrderVO;
|
import com.nq.vo.stock.ai.StockAiVO;
|
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<Long, Object> locks = new ConcurrentHashMap<>();
|
|
@Autowired
|
StockAiMapper stockAiMapper;
|
@Autowired
|
StockAiOrderMapper stockAiOrderMapper;
|
@Autowired
|
StockAiOrderPositionMapper stockAiOrderPositionMapper;
|
@Autowired
|
ISiteProductService iSiteProductService;
|
@Autowired
|
IUserService iUserService;
|
@Autowired
|
IUserAssetsServices iUserAssetsServices;
|
|
/**
|
* 获取上架ai产品
|
* @param pageNum
|
* @param pageSize
|
* @return
|
*/
|
@Override
|
public ServerResponse getStockAiList(Integer pageNum, Integer pageSize) {
|
try {
|
PageHelper.startPage(pageNum, pageSize);
|
List<StockAI> stockAiList = stockAiMapper.selectList(new QueryWrapper<StockAI>()
|
.eq("status", EStockAIStatus.online.getValue()));
|
// 获取分页信息
|
PageInfo<StockAI> 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(EStockType.MX.getCode(), user.getId());
|
/*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());
|
}*/
|
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<StockAiOrderTypeVO> stockAIOrders = stockAiOrderMapper.getStockAiOrderList(user.getId(), status);
|
// 获取分页信息
|
PageInfo<StockAiOrderTypeVO> 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<StockAiVO> stockAiList = stockAiMapper.getStockAiList(stockType, status, name);
|
// 获取分页信息
|
PageInfo<StockAiVO> pageInfo = new PageInfo<>(stockAiList);
|
|
if (!pageInfo.getList().isEmpty()) {
|
List<StockAiVO> 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 (model.getStockType().isEmpty() || model.getStockName().isEmpty() || model.getMinPrice() == null
|
|| model.getSuccessRate() == null || model.getExpectedEarning() == null || model.getStatus().isEmpty()) {
|
return ServerResponse.createByErrorMsg("请完善必填信息");
|
}
|
if (!model.getStockType().equals(EStockType.US.getCode()) && !model.getStockType().equals(EStockType.MX.getCode())) {
|
return ServerResponse.createByErrorMsg("只能选择美股或墨西哥股");
|
}
|
//新增
|
if (model.getId() == null) {
|
//查询是否存在
|
StockAI stockAI = stockAiMapper.selectOne(new QueryWrapper<StockAI>().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<StockAiOrderVO> stockAIOrders = stockAiOrderMapper.getAdminStockAiOrderList(stockType, status, userId, phone);
|
// 获取分页信息
|
PageInfo<StockAiOrderVO> pageInfo = new PageInfo<>(stockAIOrders);
|
|
if (!pageInfo.getList().isEmpty()) {
|
List<StockAiOrderVO> 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<StockAIOrderPosition> stockAIOrderPositionList = stockAiOrderPositionMapper
|
.selectList(new QueryWrapper<StockAIOrderPosition>()
|
.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 openPosition error", e);
|
}
|
return ServerResponse.createByError();
|
}
|
}
|