package com.yami.trading.api.controller.trader;
|
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.yami.trading.bean.contract.domain.ContractOrder;
|
import com.yami.trading.bean.item.domain.Item;
|
import com.yami.trading.bean.trader.domain.Trader;
|
import com.yami.trading.bean.trader.domain.TraderFollowUser;
|
import com.yami.trading.bean.trader.domain.TraderFollowUserOrder;
|
import com.yami.trading.bean.trader.domain.TraderUser;
|
import com.yami.trading.common.constants.Constants;
|
import com.yami.trading.common.exception.BusinessException;
|
import com.yami.trading.common.exception.YamiShopBindException;
|
import com.yami.trading.common.util.StringUtils;
|
import com.yami.trading.common.web.ResultObject;
|
import com.yami.trading.security.common.util.SecurityUtils;
|
import com.yami.trading.service.contract.ContractOrderService;
|
import com.yami.trading.service.item.ItemService;
|
import com.yami.trading.service.trader.TraderFollowUserOrderService;
|
import com.yami.trading.service.trader.TraderFollowUserService;
|
import com.yami.trading.service.trader.TraderService;
|
import com.yami.trading.service.trader.TraderUserService;
|
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.LogFactory;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.web.bind.annotation.CrossOrigin;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RestController;
|
|
import javax.servlet.http.HttpServletRequest;
|
import java.math.BigDecimal;
|
import java.math.RoundingMode;
|
import java.text.ParseException;
|
import java.text.SimpleDateFormat;
|
import java.util.*;
|
|
/**
|
* 用户api接口,累计数�?
|
*/
|
@RestController
|
@CrossOrigin
|
@RequestMapping()
|
public class ApiTraderUserController {
|
/**
|
*
|
*/
|
private static final long serialVersionUID = -3217562997540384508L;
|
/**
|
* 交易员api接口
|
*/
|
private static Log logger = LogFactory.getLog(ApiTraderUserController.class);
|
|
@Autowired
|
private TraderService traderService;
|
|
@Autowired
|
private TraderUserService traderUserService;
|
|
@Autowired
|
private TraderFollowUserService traderFollowUserService;
|
|
@Autowired
|
private TraderFollowUserOrderService traderFollowUserOrderService;
|
|
@Autowired
|
private ContractOrderService contractOrderService;
|
|
// private String id;
|
// private String orderBy_type;
|
// private String symbol;
|
|
@Autowired
|
private ItemService itemService;
|
|
/**
|
* 查询类型 orders 我的跟单 ,trader 我的交易
|
*/
|
// private String type;
|
/**
|
* 我的跟单查询类型�? orders 当前委托�? ,hisorders 历史委托�?
|
*/
|
// private String type_order;
|
|
// private String name;
|
|
// private int page_no;
|
|
private final String action = "/api/traderUser!";
|
|
@RequestMapping(action + "home.action")
|
public Object home() {
|
ResultObject resultObject = new ResultObject();
|
String partyId = SecurityUtils.getCurrentUserId();
|
Map<String, Object> map = new HashMap<>();
|
int followNumber = 0;
|
BigDecimal followAmount = BigDecimal.ZERO;
|
BigDecimal followProfit = BigDecimal.ZERO;
|
double totalProfit = 0d;
|
// 正在进行中的跟单
|
List<ContractOrder> contractOrderServiceList = contractOrderService.selectContractOrderByUserIdAndFollowAndState(partyId, ContractOrder.ORDER_FOLLOW, ContractOrder.STATE_SUBMITTED);
|
TraderUser traderUser = traderUserService.saveTraderUserByPartyId(partyId);
|
if(null != contractOrderServiceList) {
|
followNumber = contractOrderServiceList.size(); // 跟单中的订单数
|
followAmount = contractOrderServiceList.stream().map(ContractOrder::getDeposit).reduce(BigDecimal.ZERO, BigDecimal::add); // 跟单USDT
|
followProfit = contractOrderServiceList.stream().map(ContractOrder::getProfit).reduce(BigDecimal.ZERO, BigDecimal::add);
|
}
|
if(null != traderUser) {
|
totalProfit = traderUser.getProfit();
|
}
|
map.put("followNumber", followNumber);
|
map.put("followAmount", followAmount);
|
map.put("followProfit", followProfit);
|
map.put("totalProfit", totalProfit);
|
resultObject.setCode("0");
|
resultObject.setMsg("请求成功");
|
resultObject.setData(map);
|
return resultObject;
|
}
|
|
@RequestMapping(action + "get.action")
|
public Object get(HttpServletRequest request) {
|
ResultObject resultObject = new ResultObject();
|
String type = request.getParameter("type");
|
String page_no = request.getParameter("page_no");
|
String page_size = request.getParameter("page_size");
|
try {
|
if (StringUtils.isNullOrEmpty(page_no)) {
|
page_no = "1";
|
}
|
if (!StringUtils.isInteger(page_no)) {
|
throw new YamiShopBindException("页码不是整数");
|
}
|
if (Integer.valueOf(page_no).intValue() <= 0) {
|
throw new YamiShopBindException("页码不能小于等于0");
|
}
|
int pageSize = 10;
|
if (!StringUtils.isNullOrEmpty(page_size) && StringUtils.isInteger(page_size)) {
|
pageSize = Math.max(1, Math.min(50, Integer.parseInt(page_size)));
|
}
|
Page<?> page = new Page<>(Integer.parseInt(page_no), pageSize);
|
|
String partyId = SecurityUtils.getCurrentUserId();
|
|
TraderUser data = traderUserService.saveTraderUserByPartyId(partyId);
|
|
resultObject.setData(bulidData(data, type, page));
|
resultObject.setCode("0");
|
} catch (BusinessException e) {
|
resultObject.setCode("1");
|
resultObject.setMsg(e.getMessage());
|
} catch (Exception e) {
|
resultObject.setCode("1");
|
resultObject.setMsg("程序错误");
|
logger.error("error:", e);
|
}
|
|
return resultObject;
|
|
}
|
|
/** 交易员 SYMBOLS 可能为多品种,取第一个用于展示/查 Item */
|
private static String firstTraderSymbol(String symbolsRaw) {
|
if (symbolsRaw == null || symbolsRaw.trim().isEmpty()) {
|
return "";
|
}
|
for (String part : symbolsRaw.split("[;;,,\\s]+")) {
|
if (part != null && !part.trim().isEmpty()) {
|
return part.trim();
|
}
|
}
|
return "";
|
}
|
|
/**
|
* 供前端 i18n 映射的常见跟单失败原因(存库仍为原文)。
|
*/
|
private static String followFailReasonKey(String reason) {
|
if (reason == null) {
|
return null;
|
}
|
String r = reason.trim();
|
if (r.isEmpty()) {
|
return null;
|
}
|
if (r.contains("余额不足")) {
|
return "INSUFFICIENT_BALANCE";
|
}
|
if (r.contains("只能选择交易员带单币种")) {
|
return "SYMBOL_NOT_IN_TRADER_LIST";
|
}
|
if (r.contains("跟单参数输入错误")) {
|
return "INVALID_FOLLOW_PARAMS";
|
}
|
if (r.contains("Insufficient balance") || r.contains("insufficient balance")) {
|
return "INSUFFICIENT_BALANCE";
|
}
|
return null;
|
}
|
|
private Map<String, Object> bulidData(TraderUser entity, String type, Page page) throws ParseException {
|
|
List<Map<String, Object>> trader_order = new ArrayList<Map<String, Object>>();
|
|
List<Map<String, Object>> follow_traders = new ArrayList<Map<String, Object>>();
|
long folllow_trader_num = traderFollowUserService.countByPartyId(entity.getPartyId());
|
IPage<TraderFollowUser> traderUserPage = null;
|
|
/**
|
* 跟随的交易员(按更新时间倒序分页,最新在前)
|
*/
|
if ("trader".equals(type)) {
|
Page<TraderFollowUser> pg = new Page<>(page.getCurrent(), page.getSize());
|
traderUserPage = traderFollowUserService.pageByPartyId(pg, entity.getPartyId());
|
if (traderUserPage.getRecords() != null) {
|
for (TraderFollowUser user : traderUserPage.getRecords()) {
|
Trader trader = traderService.findByPartyId(user.getTraderPartyId());
|
if (trader == null) {
|
continue;
|
}
|
String primarySymbol = firstTraderSymbol(trader.getSymbols());
|
Item item = StringUtils.isEmptyString(primarySymbol) ? null : itemService.findBySymbol(primarySymbol);
|
Map<String, Object> follow_trader = new HashMap<String, Object>();
|
follow_trader.put("profit", user.getProfit());
|
BigDecimal profitRatio = BigDecimal.ZERO;
|
if (user.getAmountSum() > 0D) {
|
profitRatio = BigDecimal.valueOf(user.getProfit()).divide(BigDecimal.valueOf(user.getAmountSum()), 8,
|
RoundingMode.HALF_UP);
|
}
|
follow_trader.put("profitRation", profitRatio);
|
follow_trader.put("amountSum", user.getAmountSum());
|
follow_trader.put("username", trader.getName());
|
String path = Constants.WEB_URL + "/public/showimg!showImg.action?imagePath=" + trader.getImg();
|
follow_trader.put("img", path);
|
follow_trader.put("id", trader.getUuid());
|
follow_trader.put("followState", user.getState());
|
follow_trader.put("followFailReason", user.getFailReason());
|
String failKey = followFailReasonKey(user.getFailReason());
|
follow_trader.put("follow_fail_reason_key", failKey != null ? failKey : "");
|
follow_trader.put("followLastFailTime", user.getLastFailTime());
|
follow_trader.put("followType", user.getFollowType());
|
follow_trader.put("volume", user.getVolume());
|
follow_trader.put("volumeMax", user.getVolumeMax());
|
follow_trader.put("lever_rate", user.getLeverRate());
|
follow_trader.put("followNow", trader.getFollowerNow());
|
follow_trader.put("followMax", trader.getFollowerMax());
|
follow_trader.put("symbols", item != null ? item.getName() : (StringUtils.isEmptyString(trader.getSymbols()) ? "" : trader.getSymbols()));
|
follow_traders.add(follow_trader);
|
}
|
}
|
}
|
if ("orders".equals(type)) {
|
trader_order = this.traderFollowUserOrderService.getPaged(page, entity.getPartyId(), ContractOrder.STATE_SUBMITTED);
|
} else if("hisorders".equals(type)) {
|
trader_order = this.traderFollowUserOrderService.getPaged(page, entity.getPartyId(), ContractOrder.STATE_CREATED);
|
}
|
|
Map<String, Object> map = new HashMap<String, Object>();
|
|
map.put("orders", trader_order);
|
map.put("traders", follow_traders);
|
map.put("folllow_trader_num", folllow_trader_num);
|
map.put("traders_total", traderUserPage != null ? traderUserPage.getTotal() : folllow_trader_num);
|
if ("orders".equals(type) || "hisorders".equals(type)) {
|
map.put("orders_total", page.getTotal());
|
}
|
|
map.put("id", entity.getUuid());
|
|
map.put("name", entity.getName());
|
map.put("profit", entity.getProfit());
|
map.put("amount_sum", entity.getAmountSum());
|
Date date_now = new Date();// 取时�?
|
int days = daysBetween(entity.getCreateTime(), date_now);
|
if (days < 0) {
|
days = 0;
|
}
|
map.put("create_days", days);
|
|
return map;
|
|
}
|
|
/**
|
* 当前跟单持仓列表。
|
* 同时注册无 {@code !} 的路径,避免部分网关/WAF 对 {@code traderUser!positions.action} 返回 404。
|
*/
|
@RequestMapping(value = { action + "positions.action", "/api/traderUser/positions" })
|
public Object positions() {
|
ResultObject resultObject = new ResultObject();
|
String partyId = SecurityUtils.getCurrentUserId();
|
try {
|
List<ContractOrder> positions = contractOrderService.selectContractOrderByUserIdAndFollowAndState(
|
partyId, ContractOrder.ORDER_FOLLOW, ContractOrder.STATE_SUBMITTED);
|
List<Map<String, Object>> data = new ArrayList<>();
|
Map<String, String> followTraderNameCache = new HashMap<>();
|
Map<String, String> followTraderUuidCache = new HashMap<>();
|
if (positions != null) {
|
for (ContractOrder position : positions) {
|
Map<String, Object> row = contractOrderService.bulidOne(position);
|
String traderName = "";
|
String traderUuid = "";
|
if (position != null && !StringUtils.isEmptyString(position.getOrderNo())) {
|
TraderFollowUserOrder link = traderFollowUserOrderService.findByPartyIdAndOrderNo(partyId,
|
position.getOrderNo());
|
if (link != null && !StringUtils.isEmptyString(link.getTraderPartyId())) {
|
String tp = link.getTraderPartyId();
|
if (!followTraderNameCache.containsKey(tp)) {
|
Trader tr = traderService.findByPartyId(tp);
|
followTraderNameCache.put(tp, tr != null && !StringUtils.isEmptyString(tr.getName()) ? tr.getName() : "");
|
followTraderUuidCache.put(tp, tr != null && !StringUtils.isEmptyString(tr.getUuid()) ? tr.getUuid() : "");
|
}
|
traderName = followTraderNameCache.getOrDefault(tp, "");
|
traderUuid = followTraderUuidCache.getOrDefault(tp, "");
|
}
|
}
|
row.put("follow_trader_name", traderName);
|
row.put("follow_trader_id", traderUuid);
|
data.add(row);
|
}
|
}
|
resultObject.setCode("0");
|
resultObject.setData(data);
|
} catch (Exception e) {
|
resultObject.setCode("1");
|
resultObject.setMsg("程序错误");
|
logger.error("error:", e);
|
}
|
return resultObject;
|
}
|
|
public static int daysBetween(Date smdate, Date bdate) throws ParseException {
|
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
|
smdate = sdf.parse(sdf.format(smdate));
|
bdate = sdf.parse(sdf.format(bdate));
|
Calendar cal = Calendar.getInstance();
|
cal.setTime(smdate);
|
long time1 = cal.getTimeInMillis();
|
cal.setTime(bdate);
|
long time2 = cal.getTimeInMillis();
|
long between_days = (time2 - time1) / (1000 * 3600 * 24);
|
|
return Integer.parseInt(String.valueOf(between_days));
|
}
|
|
}
|