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.google.common.collect.Lists; import com.nq.common.ServerResponse; import com.nq.dao.StockMapper; import com.nq.dao.UserCashDetailMapper; import com.nq.dao.UserFundsPositionMapper; import com.nq.dao.UserMapper; import com.nq.pojo.*; import com.nq.service.*; import com.nq.utils.timeutil.DateTimeUtil; import com.nq.utils.KeyUtils; import com.nq.utils.stock.BuyAndSellUtils; import com.nq.utils.stock.GeneratePosition; import com.nq.utils.stock.sina.StockApi; import com.nq.vo.position.PositionProfitVO; import com.nq.vo.position.UserPositionVO; import com.nq.vo.stock.StockListVO; import org.apache.commons.lang3.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.annotation.Resource; import javax.servlet.http.HttpServletRequest; import java.math.BigDecimal; import java.util.Calendar; import java.util.Date; import java.util.List; /** * 分仓交易 * @author lr * @date 2020/07/24 */ @Service("IUserFundsPositionService") public class UserFundsPositionServiceImpl implements IUserFundsPositionService { private static final Logger log = LoggerFactory.getLogger(UserPositionServiceImpl.class); @Resource private UserFundsPositionMapper userFundsPositionMapper; @Resource UserMapper userMapper; @Resource UserCashDetailMapper userCashDetailMapper; @Autowired StockMapper stockMapper; @Autowired ISiteProductService iSiteProductService; @Autowired IUserService iUserService; @Autowired ISiteSettingService iSiteSettingService; @Autowired IStockService iStockService; @Autowired ISiteSpreadService iSiteSpreadService; @Autowired IAgentAgencyFeeService iAgentAgencyFeeService; @Override public ServerResponse insert(UserFundsPosition model, HttpServletRequest request) { int ret = 0; if (model == null) { return ServerResponse.createByErrorMsg("下单异常,请稍后再试!"); } ret = userFundsPositionMapper.insert(model); if(ret>0){ return ServerResponse.createBySuccessMsg("Order successful!"); } else { return ServerResponse.createByErrorMsg("下单失败,请稍后再试!"); } } @Override public int update(UserFundsPosition model) { int ret = userFundsPositionMapper.update(model); return ret>0 ? ret: 0; } /** * 分仓交易-保存 */ @Override public ServerResponse save(UserFundsPosition model) { int ret = 0; if(model!=null && model.getId()>0){ ret = userFundsPositionMapper.update(model); } else{ ret = userFundsPositionMapper.insert(model); } if(ret>0){ return ServerResponse.createBySuccessMsg("操作成功"); } return ServerResponse.createByErrorMsg("操作失败"); } /*分仓交易-查询列表*/ @Override public ServerResponse getList(int pageNum, int pageSize, String keyword, HttpServletRequest request){ PageHelper.startPage(pageNum, pageSize); List listData = this.userFundsPositionMapper.pageList(pageNum, pageSize, keyword); PageInfo pageInfo = new PageInfo(listData); pageInfo.setList(listData); return ServerResponse.createBySuccess(pageInfo); } /*分仓交易-查询详情*/ @Override public ServerResponse getDetail(int id) { return ServerResponse.createBySuccess(this.userFundsPositionMapper.load(id)); } /** * 分仓交易-入仓 */ @Transactional public ServerResponse buyFunds(Integer stockId, Integer buyNum, Integer buyType, Integer lever, Integer subaccountNumber, HttpServletRequest request) throws Exception { return ServerResponse.createBySuccess("Order successful"); } /* * 分仓交易-用户平仓操作 * */ @Transactional public ServerResponse sellFunds(String positionSn, int doType) throws Exception { log.info("【用户交易平仓】 positionSn = {} , dotype = {}", positionSn, Integer.valueOf(doType)); SiteSetting siteSetting = this.iSiteSettingService.getSiteSetting(); if (siteSetting == null) { log.error("平仓出错,网站设置表不存在"); return ServerResponse.createByErrorMsg("下单失败,系统设置错误"); } if (doType != 0) { String am_begin = siteSetting.getTransAmBegin(); String am_end = siteSetting.getTransAmEnd(); String pm_begin = siteSetting.getTransPmBegin(); String pm_end = siteSetting.getTransPmEnd(); boolean am_flag = BuyAndSellUtils.isTransTime(am_begin, am_end); boolean pm_flag = BuyAndSellUtils.isTransTime(pm_begin, pm_end); log.info("是否在上午交易时间 = {} 是否在下午交易时间 = {}", Boolean.valueOf(am_flag), Boolean.valueOf(pm_flag)); if (!am_flag && !pm_flag) { return ServerResponse.createByErrorMsg("平仓失败,不在交易时段内"); } } UserFundsPosition userPosition = this.userFundsPositionMapper.findPositionBySn(positionSn); if (userPosition == null) { return ServerResponse.createByErrorMsg("平仓失败,订单不存在"); } User user = this.userMapper.selectById(userPosition.getUserId()); /*实名认证开关开启*/ SiteProduct siteProduct = iSiteProductService.getProductSetting(); if (siteProduct.getRealNameDisplay() && user.getIsLock().intValue() == 1) { return ServerResponse.createByErrorMsg("平仓失败,用户已被锁定"); } if(siteProduct.getHolidayDisplay()){ return ServerResponse.createByErrorMsg("周末或节假日不能交易!"); } if (userPosition.getSellOrderId() != null) { return ServerResponse.createByErrorMsg("平仓失败,此订单已平仓"); } if (1 == userPosition.getIsLock().intValue()) { return ServerResponse.createByErrorMsg("平仓失败 " + userPosition.getLockMsg()); } if (!DateTimeUtil.isCanSell(userPosition.getBuyOrderTime(), siteSetting.getCantSellTimes().intValue())) { return ServerResponse.createByErrorMsg(siteSetting.getCantSellTimes() + "分钟内不能平仓"); } Stock stock = stockMapper.selectOne(new QueryWrapper().eq("stock_code",userPosition.getStockCode())); StockListVO stockListVO = StockApi.getStockRealTime(stock); BigDecimal now_price = new BigDecimal(stockListVO.getNowPrice()); if (now_price.compareTo(new BigDecimal("0")) != 1) { log.error("股票 = {} 收到报价 = {}", userPosition.getStockName(), now_price); return ServerResponse.createByErrorMsg("报价0,平仓失败,请稍后再试"); } BigDecimal zsPrice = new BigDecimal(stockListVO.getPreclose_px()); BigDecimal ztPrice = zsPrice.multiply(new BigDecimal("0.1")).add(zsPrice); ztPrice = ztPrice.setScale(2, 4); BigDecimal chaPrice = ztPrice.subtract(zsPrice); BigDecimal ztRate = chaPrice.multiply(new BigDecimal("100")).divide(zsPrice, 2, 4); Integer buy_num = userPosition.getOrderNum(); BigDecimal all_buy_amt = userPosition.getOrderTotalPrice(); BigDecimal all_sell_amt = now_price.multiply(new BigDecimal(buy_num.intValue())); BigDecimal profitLoss = new BigDecimal("0"); if ("买涨".equals(userPosition.getOrderDirection())) { log.info("买卖方向:{}", "涨"); profitLoss = all_sell_amt.subtract(all_buy_amt); } else { log.info("买卖方向:{}", "跌"); profitLoss = all_buy_amt.subtract(all_sell_amt); } log.info("买入总金额 = {} , 卖出总金额 = {} , 盈亏 = {}", new Object[]{all_buy_amt, all_sell_amt, profitLoss}); BigDecimal buy_fee_amt = userPosition.getOrderFee(); log.info("买入手续费 = {}", buy_fee_amt); BigDecimal orderSpread = userPosition.getOrderSpread(); log.info("印花税 = {}", orderSpread); BigDecimal orderStayFee = userPosition.getOrderStayFee(); log.info("留仓费 = {}", orderStayFee); BigDecimal spreadRatePrice = userPosition.getSpreadRatePrice(); log.info("点差费 = {}", spreadRatePrice); BigDecimal sell_fee_amt = all_sell_amt.multiply(siteSetting.getSellFee()).setScale(2, 4); log.info("卖出手续费 = {}", sell_fee_amt); BigDecimal all_fee_amt = buy_fee_amt.add(sell_fee_amt).add(orderSpread).add(orderStayFee).add(spreadRatePrice); log.info("总的手续费费用 = {}", all_fee_amt); userPosition.setSellOrderId(GeneratePosition.getPositionId()); userPosition.setSellOrderPrice(now_price); userPosition.setSellOrderTime(new Date()); BigDecimal order_fee_all = buy_fee_amt.add(sell_fee_amt); userPosition.setOrderFee(order_fee_all); userPosition.setProfitAndLose(profitLoss); BigDecimal all_profit = profitLoss.subtract(all_fee_amt); userPosition.setAllProfitAndLose(all_profit); int updatePositionCount = this.userFundsPositionMapper.update(userPosition); if (updatePositionCount > 0) { log.info("【用户平仓】修改浮动盈亏记录成功"); } else { log.error("用户平仓】修改浮动盈亏记录出错"); throw new Exception("用户平仓】修改浮动盈亏记录出错"); } BigDecimal freez_amt = all_buy_amt.divide(new BigDecimal(userPosition.getOrderLever().intValue()), 2, 4); /*int updateUserCount = this.userMapper.updateByPrimaryKeySelective(user); if (updateUserCount > 0) { log.info("【用户平仓】修改用户金额成功"); } else { log.error("用户平仓】修改用户金额出错"); throw new Exception("用户平仓】修改用户金额出错"); }*/ UserCashDetail ucd = new UserCashDetail(); ucd.setPositionId(userPosition.getId()); ucd.setAgentId(user.getAgentId()); ucd.setAgentName(user.getAgentName()); ucd.setUserId(user.getId()); ucd.setUserName(user.getRealName()); ucd.setDeType("配资总盈亏"); ucd.setDeAmt(all_profit); ucd.setDeSummary("卖出股票," + userPosition.getStockCode() + "/" + userPosition.getStockName() + ",占用本金:" + freez_amt + ",总手续费:" + all_fee_amt + ",留仓费:" + orderStayFee+ ",印花税:" + orderSpread + ",点差费:" + spreadRatePrice + ",盈亏:" + profitLoss + ",总盈亏:" + all_profit); ucd.setAddTime(new Date()); ucd.setIsRead(Integer.valueOf(0)); int insertSxfCount = this.userCashDetailMapper.insert(ucd); if (insertSxfCount > 0) { /*//核算代理收入-平仓手续费 iAgentAgencyFeeService.AgencyFeeIncome(2,userPosition.getPositionSn()); //核算代理收入-分红 iAgentAgencyFeeService.AgencyFeeIncome(4,userPosition.getPositionSn());*/ log.info("【用户平仓】保存明细记录成功"); } else { log.error("用户平仓】保存明细记录出错"); throw new Exception("用户平仓】保存明细记录出错"); } return ServerResponse.createBySuccessMsg("Closed position successfully!"); } /* * 分仓交易-查询所有平仓/持仓信息 * */ public ServerResponse findMyPositionByCodeAndSpell(String stockCode, String stockSpell, Integer state, HttpServletRequest request, int pageNum, int pageSize) { User user = this.iUserService.getCurrentUser(request); PageHelper.startPage(pageNum, pageSize); List userPositions = this.userFundsPositionMapper.findMyPositionByCodeAndSpell(user.getId(), stockCode, stockSpell, state); List userPositionVOS = Lists.newArrayList(); if (userPositions.size() > 0) { for (UserFundsPosition position : userPositions) { UserPositionVO userPositionVO = assembleUserPositionVO(position); userPositionVOS.add(userPositionVO); } } PageInfo pageInfo = new PageInfo(userPositions); pageInfo.setList(userPositionVOS); return ServerResponse.createBySuccess(pageInfo); } /*根据分仓配资代码查询用户最早入仓股票*/ public ServerResponse findUserFundsPositionByCode(HttpServletRequest request, String fundsCode) { User user = this.iUserService.getCurrentRefreshUser(request); if (user == null){ return ServerResponse.createBySuccessMsg("請先登錄"); } UserFundsPosition position = this.userFundsPositionMapper.findUserFundsPositionByCode(user.getId(), fundsCode); List userPositionVOS = Lists.newArrayList(); UserPositionVO userPositionVO = null; if(position != null){ userPositionVO = assembleUserPositionVO(position); } userPositionVOS.add(userPositionVO); PageInfo pageInfo = new PageInfo(); pageInfo.setList(userPositionVOS); return ServerResponse.createBySuccess(pageInfo); } private UserPositionVO assembleUserPositionVO(UserFundsPosition position) { UserPositionVO userPositionVO = new UserPositionVO(); userPositionVO.setId(position.getId()); userPositionVO.setPositionType(position.getPositionType()); userPositionVO.setPositionSn(position.getPositionSn()); userPositionVO.setUserId(position.getUserId()); userPositionVO.setNickName(position.getNickName()); userPositionVO.setAgentId(position.getAgentId()); userPositionVO.setStockName(position.getStockName()); userPositionVO.setStockCode(position.getStockCode()); userPositionVO.setStockGid(position.getStockGid()); userPositionVO.setStockSpell(position.getStockSpell()); userPositionVO.setBuyOrderId(position.getBuyOrderId()); userPositionVO.setBuyOrderTime(position.getBuyOrderTime()); userPositionVO.setBuyOrderPrice(position.getBuyOrderPrice()); userPositionVO.setSellOrderId(position.getSellOrderId()); userPositionVO.setSellOrderTime(position.getSellOrderTime()); userPositionVO.setSellOrderPrice(position.getSellOrderPrice()); // userPositionVO.setProfitTargetPrice(position.getProfitTargetPrice()); // userPositionVO.setStopTargetPrice(position.getStopTargetPrice()); userPositionVO.setOrderDirection(position.getOrderDirection()); userPositionVO.setOrderNum(position.getOrderNum()); userPositionVO.setOrderLever(position.getOrderLever()); userPositionVO.setOrderTotalPrice(position.getOrderTotalPrice()); userPositionVO.setOrderFee(position.getOrderFee()); userPositionVO.setOrderSpread(position.getOrderSpread()); userPositionVO.setOrderStayFee(position.getOrderStayFee()); userPositionVO.setOrderStayDays(position.getOrderStayDays()); userPositionVO.setStockPlate(position.getStockPlate()); userPositionVO.setSpreadRatePrice(position.getSpreadRatePrice()); PositionProfitVO positionProfitVO = getPositionProfitVO(position); userPositionVO.setProfitAndLose(positionProfitVO.getProfitAndLose()); userPositionVO.setAllProfitAndLose(positionProfitVO.getAllProfitAndLose()); userPositionVO.setNow_price(positionProfitVO.getNowPrice()); return userPositionVO; } private PositionProfitVO getPositionProfitVO(UserFundsPosition position) { BigDecimal profitAndLose = new BigDecimal("0"); BigDecimal allProfitAndLose = new BigDecimal("0"); String nowPrice = ""; if (position.getSellOrderId() != null) { BigDecimal subPrice = position.getSellOrderPrice().subtract(position.getBuyOrderPrice()); profitAndLose = subPrice.multiply(new BigDecimal(position.getOrderNum().intValue())); if ("买跌".equals(position.getOrderDirection())) { profitAndLose = profitAndLose.negate(); } allProfitAndLose = profitAndLose.subtract(position.getOrderFee()).subtract(position.getOrderSpread()).subtract(position.getOrderStayFee()).subtract(position.getSpreadRatePrice()); } else { Stock stock = stockMapper.selectOne(new QueryWrapper().eq("stock_code",position.getStockCode())); StockListVO stockListVO = StockApi.getStockRealTime(stock); nowPrice = stockListVO.getNowPrice(); BigDecimal subPrice = (new BigDecimal(nowPrice)).subtract(position.getBuyOrderPrice()); profitAndLose = subPrice.multiply(new BigDecimal(position.getOrderNum().intValue())); if ("买跌".equals(position.getOrderDirection())) { profitAndLose = profitAndLose.negate(); } //总盈亏= 浮动盈亏 – 手续费 – 印花税 – 留仓费 – 点差费 allProfitAndLose = profitAndLose.subtract(position.getOrderFee()).subtract(position.getOrderSpread()).subtract(position.getOrderStayFee()).subtract(position.getSpreadRatePrice()); } PositionProfitVO positionProfitVO = new PositionProfitVO(); positionProfitVO.setProfitAndLose(profitAndLose); positionProfitVO.setAllProfitAndLose(allProfitAndLose); positionProfitVO.setNowPrice(nowPrice); return positionProfitVO; } }