From 51571c5cde2c49613346418e75e3fd8bcae3e13a Mon Sep 17 00:00:00 2001 From: Helius <wangdoubleone@gmail.com> Date: Tue, 16 Jun 2020 18:52:41 +0800 Subject: [PATCH] finish contract holding order --- src/main/java/com/xcong/excoin/common/utils/CacheSettingUtils.java | 82 +++ src/main/java/com/xcong/excoin/modules/contract/entity/ContractHoldOrderEntity.java | 162 ++++++ src/main/java/com/xcong/excoin/modules/contract/service/impl/ContractHoldOrderServiceImpl.java | 74 +++ src/main/java/com/xcong/excoin/common/utils/CoinTypeConvert.java | 50 ++ src/main/java/com/xcong/excoin/modules/contract/entity/PlatformTradeSettingEntity.java | 63 ++ src/main/java/com/xcong/excoin/modules/contract/entity/PlatformLeverageSettingEntity.java | 40 + src/main/java/com/xcong/excoin/modules/contract/mapper/TradeSettingDao.java | 21 src/main/java/com/xcong/excoin/modules/contract/entity/PlatformSymbolsSkuEntity.java | 33 + src/main/java/com/xcong/excoin/modules/contract/controller/ContractOrderController.java | 44 + src/main/resources/templates/febs/views/modules/contract/hold-list.html | 175 +++++++ pom.xml | 6 src/main/java/com/xcong/excoin/modules/contract/mapper/ContractHoldOrderMapper.java | 15 src/main/java/com/xcong/excoin/modules/contract/controller/MemberAssetsController.java | 8 src/main/java/com/xcong/excoin/common/utils/RedisUtils.java | 554 +++++++++++++++++++++++ src/main/java/com/xcong/excoin/modules/contract/controller/CoinController.java | 8 src/main/java/com/xcong/excoin/modules/contract/controller/ViewController.java | 23 src/main/java/com/xcong/excoin/modules/contract/service/IContractHoldOrderService.java | 15 src/main/resources/application-dev.yml | 2 src/main/resources/mapper/modules/ContractHoldOrderMapper.xml | 18 src/main/resources/mapper/modules/TradeSettingDao.xml | 26 + 20 files changed, 1,418 insertions(+), 1 deletions(-) diff --git a/pom.xml b/pom.xml index ef42987..402f4dd 100644 --- a/pom.xml +++ b/pom.xml @@ -208,6 +208,12 @@ <artifactId>xml-apis</artifactId> <version>1.4.01</version> </dependency> + + <dependency> + <groupId>cn.hutool</groupId> + <artifactId>hutool-all</artifactId> + <version>5.3.1</version> + </dependency> </dependencies> <build> diff --git a/src/main/java/com/xcong/excoin/common/utils/CacheSettingUtils.java b/src/main/java/com/xcong/excoin/common/utils/CacheSettingUtils.java new file mode 100644 index 0000000..fa87f35 --- /dev/null +++ b/src/main/java/com/xcong/excoin/common/utils/CacheSettingUtils.java @@ -0,0 +1,82 @@ +package com.xcong.excoin.common.utils; + +import cn.hutool.core.bean.BeanUtil; +import com.xcong.excoin.modules.contract.entity.PlatformSymbolsSkuEntity; +import com.xcong.excoin.modules.contract.entity.PlatformTradeSettingEntity; +import com.xcong.excoin.modules.contract.mapper.TradeSettingDao; +import org.apache.commons.collections.CollectionUtils; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import java.math.BigDecimal; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @author wzy + * @date 2020-05-28 + **/ +@Component +public class CacheSettingUtils { + + + /** + * 交易设置缓存Key + */ + private final static String TRADE_SETTING_KEY = "trade_setting_key"; + + /** + * 币种规格缓存key + */ + private final static String TRADE_SYMBOL_SKU_KEY = "trade_symbol_sku_key"; + + @Resource + private TradeSettingDao tradeSettingDao; + + @Resource + private RedisUtils redisUtils; + + + /** + * 获取币种规格 + * + * @param symbol + * @return + */ + public BigDecimal getSymbolSku(String symbol) { + Object hget = redisUtils.hget(TRADE_SYMBOL_SKU_KEY, symbol); + if (hget == null) { + List<PlatformSymbolsSkuEntity> symbolSkubySymbol = tradeSettingDao.findAllSymbolSkubySymbol(); + Map<String, Object> map = new HashMap<String, Object>(); + if (CollectionUtils.isNotEmpty(symbolSkubySymbol)) { + for (PlatformSymbolsSkuEntity symbolSku : symbolSkubySymbol) { + map.put(symbolSku.getName(), symbolSku.getLotnumber()); + } + // 存入redis + redisUtils.hmset(TRADE_SYMBOL_SKU_KEY, map); + } + + hget = redisUtils.hget(TRADE_SYMBOL_SKU_KEY, symbol); + } + + return new BigDecimal(hget.toString()); + } + + /** + * 获取交易设置缓存 + * + * @return + */ + public PlatformTradeSettingEntity getTradeSetting() { + Map<Object, Object> hmget = redisUtils.hmget(TRADE_SETTING_KEY); + + if (hmget == null || hmget.size() == 0) { + PlatformTradeSettingEntity tradeSetting = tradeSettingDao.findTradeSetting(); + redisUtils.hmset(TRADE_SETTING_KEY, BeanUtil.beanToMap(tradeSetting)); + return tradeSetting; + } + return BeanUtil.mapToBean(hmget, PlatformTradeSettingEntity.class, true); + } + +} diff --git a/src/main/java/com/xcong/excoin/common/utils/CoinTypeConvert.java b/src/main/java/com/xcong/excoin/common/utils/CoinTypeConvert.java new file mode 100644 index 0000000..ef93a58 --- /dev/null +++ b/src/main/java/com/xcong/excoin/common/utils/CoinTypeConvert.java @@ -0,0 +1,50 @@ +package com.xcong.excoin.common.utils; + +/** + * @author wzy + * @date 2020-05-28 + **/ +public class CoinTypeConvert { + + public static String convert(String symbol) { + switch (symbol) { + case "btcusdt": + return "BTC/USDT"; + case "ethusdt": + return "ETH/USDT"; + case "xrpusdt": + return "XRP/USDT"; + case "ltcusdt": + return "LTC/USDT"; + case "bchusdt": + return "BCH/USDT"; + case "eosusdt": + return "EOS/USDT"; + case "etcusdt": + return "ETC/USDT"; + default: + return null; + } + } + + public static String convertToKey(String symbol) { + switch (symbol) { + case "BTC/USDT": + return "BTC_NEW_PRICE"; + case "ETH/USDT": + return "ETH_NEW_PRICE"; + case "XRP/USDT": + return "XRP_NEW_PRICE"; + case "LTC/USDT": + return "LTC_NEW_PRICE"; + case "BCH/USDT": + return "BCH_NEW_PRICE"; + case "EOS/USDT": + return "EOS_NEW_PRICE"; + case "ETC/USDT": + return "ETC_NEW_PRICE"; + default: + return null; + } + } +} diff --git a/src/main/java/com/xcong/excoin/common/utils/RedisUtils.java b/src/main/java/com/xcong/excoin/common/utils/RedisUtils.java new file mode 100644 index 0000000..4a4ad1f --- /dev/null +++ b/src/main/java/com/xcong/excoin/common/utils/RedisUtils.java @@ -0,0 +1,554 @@ +package com.xcong.excoin.common.utils; + +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +import javax.annotation.Resource; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.TimeUnit; + +/** + * @Author wzy + * @Date 2020/5/10 + * @email wangdoubleone@gmail.com + * @Version V1.0 + **/ +@Component +public class RedisUtils { + + + @Resource + private RedisTemplate<String, Object> redisTemplate; + + + // =============================common============================ + /** + * 指定缓存失效时间 + * @param key 键 + * @param time 时间(秒) + * @return + */ + public boolean expire(String key, long time) { + try { + if (time > 0) { + redisTemplate.expire(key, time, TimeUnit.SECONDS); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 根据key 获取过期时间 + * @param key 键 不能为null + * @return 时间(秒) 返回0代表为永久有效 + */ + public long getExpire(String key) { + return redisTemplate.getExpire(key, TimeUnit.SECONDS); + } + + /** + * 判断key是否存在 + * @param key 键 + * @return true 存在 false不存在 + */ + public boolean hasKey(String key) { + try { + return redisTemplate.hasKey(key); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除缓存 + * @param key 可以传一个值 或多个 + */ + @SuppressWarnings("unchecked") + public void del(String... key) { + if (key != null && key.length > 0) { + if (key.length == 1) { + redisTemplate.delete(key[0]); + } else { + redisTemplate.delete(CollectionUtils.arrayToList(key)); + } + } + } + + // ============================String============================= + /** + * 普通缓存获取 + * @param key 键 + * @return 值 + */ + public Object get(String key) { + return key == null ? null : redisTemplate.opsForValue().get(key); + } + + + /** + * 普通缓存获取 + * @param key 键 + * @return 值 + */ + public String getString(String key) { + Object obj = key == null ? null : redisTemplate.opsForValue().get(key); + if(obj!=null){ + return obj.toString(); + } + return null; + } + + /** + * 普通缓存放入 + * @param key 键 + * @param value 值 + * @return true成功 false失败 + */ + public boolean set(String key, Object value) { + try { + redisTemplate.opsForValue().set(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 普通缓存放入并设置时间 + * @param key 键 + * @param value 值 + * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 + * @return true成功 false 失败 + */ + public boolean set(String key, Object value, long time) { + try { + if (time > 0) { + redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); + } else { + set(key, value); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + public boolean setNotExist(String key, Object value, long time) { + return redisTemplate.opsForValue().setIfAbsent(key, value, time, TimeUnit.SECONDS); + } + + /** + * 递增 + * @param key 键 + * @param delta 要增加几(大于0) + * @return + */ + public long incr(String key, long delta) { + if (delta < 0) { + throw new RuntimeException("递增因子必须大于0"); + } + return redisTemplate.opsForValue().increment(key, delta); + } + + /** + * 递减 + * @param key 键 + * @param delta 要减少几(小于0) + * @return + */ + public long decr(String key, long delta) { + if (delta < 0) { + throw new RuntimeException("递减因子必须大于0"); + } + return redisTemplate.opsForValue().increment(key, -delta); + } + + + // ================================Map================================= + + /** + * HashGet + * @param key 键 不能为null + * @param item 项 不能为null + * @return 值 + */ + public Object hget(String key, String item) { + return redisTemplate.opsForHash().get(key, item); + } + + /** + * 获取hashKey对应的所有键值 + * @param key 键 + * @return 对应的多个键值 + */ + public Map<Object, Object> hmget(String key) { + return redisTemplate.opsForHash().entries(key); + } + /** + * HashSet + + * @param key 键 + * @param map 对应多个键值 + * @return true 成功 false 失败 + */ + public boolean hmset(String key, Map<String, Object> map) { + try { + redisTemplate.opsForHash().putAll(key, map); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + /** + * HashSet 并设置时间 + * @param key 键 + * @param map 应多个键值 + * @param time 时间(秒) + * @return true成功 false失败 + */ + public boolean hmset(String key, Map<String, Object> map, long time) { + try { + redisTemplate.opsForHash().putAll(key, map); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * @param key 键 + * @param item 项 + * @param value 值 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value) { + try { + redisTemplate.opsForHash().put(key, item, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + /** + * 向一张hash表中放入数据,如果不存在将创建 + * @param key 键 + * @param item 项 + * @param value 值 + * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value, long time) { + try { + redisTemplate.opsForHash().put(key, item, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + /** + * 删除hash表中的值 + * @param key 键 不能为null + * @param item 项 可以使多个 不能为null + */ + public void hdel(String key, Object... item) { + redisTemplate.opsForHash().delete(key, item); + } + /** + * 判断hash表中是否有该项的值 + * @param key 键 不能为null + * @param item 项 不能为null + * @return true 存在 false不存在 + */ + public boolean hHasKey(String key, String item) { + return redisTemplate.opsForHash().hasKey(key, item); + } + + /** + * hash递增 如果不存在,就会创建一个 并把新增后的值返回 + * @param key 键 + * @param item 项 + * @param by 要增加几(大于0) + * @return + */ + public double hincr(String key, String item, double by) { + return redisTemplate.opsForHash().increment(key, item, by); + } + + /** + * hash递减 + * @param key 键 + * @param item 项 + * @param by 要减少记(小于0) + * @return + */ + public double hdecr(String key, String item, double by) { + return redisTemplate.opsForHash().increment(key, item, -by); + } + // ============================set============================= + /** + * 根据key获取Set中的所有值 + * @param key 键 + * @return + */ + public Set<Object> sGet(String key) { + try { + return redisTemplate.opsForSet().members(key); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + /** + * 根据value从一个set中查询,是否存在 + * @param key 键 + * @param value 值 + * @return true 存在 false不存在 + */ + public boolean sHasKey(String key, Object value) { + try { + return redisTemplate.opsForSet().isMember(key, value); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + /** + * 将数据放入set缓存 + * @param key 键 + * @param values 值 可以是多个 + * @return 成功个数 + */ + public long sSet(String key, Object... values) { + try { + return redisTemplate.opsForSet().add(key, values); + } catch (Exception e) { + e.printStackTrace(); + + return 0; + } + } + /** + 336 + * 将set数据放入缓存 + 337 + * @param key 键 + * @param time 时间(秒) + * @param values 值 可以是多个 + * @return 成功个数 + */ + public long sSetAndTime(String key, long time, Object... values) { + try { + Long count = redisTemplate.opsForSet().add(key, values); + if (time > 0) + expire(key, time); + return count; + + }catch(Exception e) { + e.printStackTrace(); + return 0; + } + } + /** + * 获取set缓存的长度 + * @param key 键 + * @return + */ + + public long sGetSetSize(String key) { + try { + return redisTemplate.opsForSet().size(key); + + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + + } + + /** + * 移除值为value的 + * @param key 键 + * @param values 值 可以是多个 + * @return 移除的个数 + + */ + public long setRemove(String key, Object... values) { + try { + Long count = redisTemplate.opsForSet().remove(key, values); + return count; + + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + // ===============================list================================= + /** + * 获取list缓存的内容 * @param key 键 + * @param start 开始 + * @param end 结束 0 到 -1代表所有值 + * @return + */ + public List<Object> lGet(String key, long start, long end) { + try { + return redisTemplate.opsForList().range(key, start, end); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + + } + + /** + * 获取list缓存的长度 + * @param key 键 + + * @return + */ + public long lGetListSize(String key) { try { + return redisTemplate.opsForList().size(key); + } catch (Exception e) { + + e.printStackTrace(); + return 0; + } + } /** + * 通过索引 获取list中的值 + * @param key 键 + * @param index 索引 index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推 + * @return + */ + public Object lGetIndex(String key, long index) { + + try { + return redisTemplate.opsForList().index(key, index); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 将list放入缓存 + * @param key 键 + * @param value 值 + * @return + */ + public boolean lSet(String key, Object value) { + try { + redisTemplate.opsForList().rightPush(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public boolean lSet(String key, Object value, long time) { + try { + redisTemplate.opsForList().rightPush(key, value); + if (time > 0) + expire(key, time); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + /** + * 将list放入缓存 + * @param key 键 + * @param value 值 + * @return + */ + public boolean lSet(String key, List<Object> value) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public boolean lSet(String key, List<Object> value, long time) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + if (time > 0) + expire(key, time); + return true; + + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + /** + * 根据索引修改list中的某条数据 + * @param key 键 + * @param index 索引 + * @param value 值 + * @return + */ + public boolean lUpdateIndex(String key, long index, Object value) { + try { + redisTemplate.opsForList().set(key, index, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + + /** + * 移除N个值为value + * @param key 键 + * @param count 移除多少个 + * @param value 值 + * @return 移除的个数 + */ + public long lRemove(String key, long count, Object value) { + try { + return redisTemplate.opsForList().remove(key, count, value); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } +} diff --git a/src/main/java/com/xcong/excoin/modules/contract/controller/CoinController.java b/src/main/java/com/xcong/excoin/modules/contract/controller/CoinController.java new file mode 100644 index 0000000..65a5fd9 --- /dev/null +++ b/src/main/java/com/xcong/excoin/modules/contract/controller/CoinController.java @@ -0,0 +1,8 @@ +package com.xcong.excoin.modules.contract.controller; + +/** + * @author wzy + * @date 2020-06-16 + **/ +public class CoinController { +} diff --git a/src/main/java/com/xcong/excoin/modules/contract/controller/ContractOrderController.java b/src/main/java/com/xcong/excoin/modules/contract/controller/ContractOrderController.java new file mode 100644 index 0000000..408f862 --- /dev/null +++ b/src/main/java/com/xcong/excoin/modules/contract/controller/ContractOrderController.java @@ -0,0 +1,44 @@ +package com.xcong.excoin.modules.contract.controller; + +import com.xcong.excoin.common.controller.BaseController; +import com.xcong.excoin.common.entity.FebsConstant; +import com.xcong.excoin.common.entity.FebsResponse; +import com.xcong.excoin.common.entity.QueryRequest; +import com.xcong.excoin.modules.contract.entity.ContractHoldOrderEntity; +import com.xcong.excoin.modules.contract.service.IContractHoldOrderService; +import com.xcong.excoin.system.entity.User; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.Map; + +/** + * @author wzy + * @date 2020-06-16 + **/ +@Slf4j +@Validated +@RestController +@RequestMapping(value = "/order") +@RequiredArgsConstructor +public class ContractOrderController extends BaseController { + + private final IContractHoldOrderService contractHoldOrderService; + + @GetMapping("getHoldList") + public FebsResponse getHoldList(ContractHoldOrderEntity contractHoldOrderEntity, QueryRequest request) { + User user = getCurrentUser(); + if (user.getType().equals(FebsConstant.USER_TYPE_ADMIN)) { + contractHoldOrderEntity.setInviteId(FebsConstant.DEFAULT_REFERER_ID); + } else { + contractHoldOrderEntity.setInviteId(user.getInviteId()); + } + Map<String, Object> data = getDataTable(contractHoldOrderService.findHoldList(contractHoldOrderEntity, request)); + return new FebsResponse().success().data(data); + } +} diff --git a/src/main/java/com/xcong/excoin/modules/contract/controller/MemberAssetsController.java b/src/main/java/com/xcong/excoin/modules/contract/controller/MemberAssetsController.java new file mode 100644 index 0000000..c4fb9c1 --- /dev/null +++ b/src/main/java/com/xcong/excoin/modules/contract/controller/MemberAssetsController.java @@ -0,0 +1,8 @@ +package com.xcong.excoin.modules.contract.controller; + +/** + * @author wzy + * @date 2020-06-16 + **/ +public class MemberAssetsController { +} diff --git a/src/main/java/com/xcong/excoin/modules/contract/controller/ViewController.java b/src/main/java/com/xcong/excoin/modules/contract/controller/ViewController.java new file mode 100644 index 0000000..3ce0be7 --- /dev/null +++ b/src/main/java/com/xcong/excoin/modules/contract/controller/ViewController.java @@ -0,0 +1,23 @@ +package com.xcong.excoin.modules.contract.controller; + +import com.xcong.excoin.common.entity.FebsConstant; +import com.xcong.excoin.common.utils.FebsUtil; +import org.apache.shiro.authz.annotation.RequiresPermissions; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; + +/** + * @author wzy + * @date 2020-06-16 + **/ +@Controller("contract") +@RequestMapping(FebsConstant.VIEW_PREFIX + "/contract") +public class ViewController { + + @GetMapping("holdList") + @RequiresPermissions("hold:view") + public String holdList() { + return FebsUtil.view("modules/contract/hold-list"); + } +} diff --git a/src/main/java/com/xcong/excoin/modules/contract/entity/ContractHoldOrderEntity.java b/src/main/java/com/xcong/excoin/modules/contract/entity/ContractHoldOrderEntity.java new file mode 100644 index 0000000..23c1f47 --- /dev/null +++ b/src/main/java/com/xcong/excoin/modules/contract/entity/ContractHoldOrderEntity.java @@ -0,0 +1,162 @@ +package com.xcong.excoin.modules.contract.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.xcong.excoin.common.entity.BaseEntity; +import lombok.Data; + +import java.math.BigDecimal; + +/** + * 合约持仓订单表 + * + * @author wzy + * @date 2020-05-27 + **/ +@Data +@TableName("contract_hold_order") +public class ContractHoldOrderEntity extends BaseEntity { + + /** + * 是否可平仓 1-是 + */ + public static final int ORDER_CAN_CLOSING_Y = 1; + /** + * 是否可平仓 0-否 + */ + public static final int ORDER_CAN_CLOSING_N = 0; + + /** + * 开多 + */ + public static final int OPENING_TYPE_MORE = 1; + + /** + * 开空 + */ + public static final int OPENING_TYPE_LESS = 2; + + /** + * 交易类型 市价 + */ + public static final int TRADE_TYPE_MARK = 1; + + /** + * 交易类型 限价 + */ + public static final int TRADE_TYPE_LIMIT = 2; + + /** + * 会员Id + */ + private Long memberId; + + /** + * 订单编号 + */ + private String orderNo; + + /** + * 仓位类型 1-逐仓 2-全仓 + */ + private int positionType; + + /** + * 交易类型 1-市价 2-限价 + */ + private int tradeType; + + /** + * 币种 + */ + private String symbol; + + /** + * 手数 + */ + private int symbolCnt; + + /** + * 可平张数(仅全仓模式) + */ + private int symbolCntSale; + + /** + * 币种规格 + */ + private BigDecimal symbolSku; + + /** + * 开仓价 + */ + private BigDecimal openingPrice; + + /** + * 开仓类型 1-开多 2-开空 + */ + private int openingType; + + /** + * 开仓手续费 + */ + private BigDecimal openingFeeAmount; + + /** + * 保证金 + */ + private BigDecimal bondAmount; + + /** + * 杠杆倍率 + */ + private int leverRatio; + + /** + * 市场价 + */ + private BigDecimal markPrice; + + /** + * 止损价 + */ + private BigDecimal stopLossPrice; + + /** + * 止盈价 + */ + private BigDecimal stopProfitPrice; + + /** + * 预付款金额 + */ + private BigDecimal prePaymentAmount; + + /** + * 预估强平价 + */ + private BigDecimal forceClosingPrice; + + private int operateNo; + + /** + * 是否可平仓 0-否 1-是 + */ + private int isCanClosing; + + /** + * 批次号 队列平仓时使用,避免重复 + */ + public String batchNo; + + /** + * 持仓费 + */ + private BigDecimal holdAmount; + + private String inviteId; + + private BigDecimal loseOrProfit; + + private BigDecimal returnRatio; + + private int isProfit; +} diff --git a/src/main/java/com/xcong/excoin/modules/contract/entity/PlatformLeverageSettingEntity.java b/src/main/java/com/xcong/excoin/modules/contract/entity/PlatformLeverageSettingEntity.java new file mode 100644 index 0000000..1d4f210 --- /dev/null +++ b/src/main/java/com/xcong/excoin/modules/contract/entity/PlatformLeverageSettingEntity.java @@ -0,0 +1,40 @@ +package com.xcong.excoin.modules.contract.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; + +/** + * 杠杆设置表 + */ +@Data +@TableName("platform_leverage_setting") +public class PlatformLeverageSettingEntity implements Serializable { + + /** + * + */ + private static final long serialVersionUID = 1L; + @TableId(value = "id",type = IdType.AUTO) + private Long id; + /** + * 杠杆值 + */ + private String value; + /** + * 杠杆名称 + */ + private String name; + /** + * 币种 + */ + private String symbol; + /** + * 维持保证金率 + */ + private String prePriceRate; + +} diff --git a/src/main/java/com/xcong/excoin/modules/contract/entity/PlatformSymbolsSkuEntity.java b/src/main/java/com/xcong/excoin/modules/contract/entity/PlatformSymbolsSkuEntity.java new file mode 100644 index 0000000..383adfb --- /dev/null +++ b/src/main/java/com/xcong/excoin/modules/contract/entity/PlatformSymbolsSkuEntity.java @@ -0,0 +1,33 @@ +package com.xcong.excoin.modules.contract.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.math.BigDecimal; + +/** + * 币种规格表 + * @author helius + */ +@Data +@TableName("platform_symbols_sku") +public class PlatformSymbolsSkuEntity implements Serializable { + /** + * + */ + private static final long serialVersionUID = 1L; + @TableId(value = "id",type = IdType.AUTO) + private Long id; + /** + * 币种名称 + */ + private String name; + /** + * 规格 + */ + private BigDecimal lotnumber; + +} diff --git a/src/main/java/com/xcong/excoin/modules/contract/entity/PlatformTradeSettingEntity.java b/src/main/java/com/xcong/excoin/modules/contract/entity/PlatformTradeSettingEntity.java new file mode 100644 index 0000000..1f60ee5 --- /dev/null +++ b/src/main/java/com/xcong/excoin/modules/contract/entity/PlatformTradeSettingEntity.java @@ -0,0 +1,63 @@ +package com.xcong.excoin.modules.contract.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.math.BigDecimal; + +/** + * 交易设置表 + * @author Administrator + * + */ +@Data +@TableName("platform_trade_setting") +public class PlatformTradeSettingEntity implements Serializable { + + /** + * + */ + private static final long serialVersionUID = 1L; + @TableId(value = "id",type = IdType.AUTO) + private Long id; + /** + * 点差 + */ + private BigDecimal spread; + /** + * 杠杆 + */ + private BigDecimal leverageRatio; + /** + * 爆仓 + */ + private BigDecimal outstock; + /** + * 手续费率 + */ + private BigDecimal feeRatio; + /** + * 币币手续费率 + */ + private BigDecimal coinFeeRatio; + /** + * 代理返佣比例 + */ + private BigDecimal agentReturnRatio; + /** + * 持仓系数 + */ + private BigDecimal doingRatio; + /** + * 预估强平价系数 + */ + private BigDecimal forceParam; + + /** + *盈亏难度系数 + */ + private BigDecimal profitParam; +} diff --git a/src/main/java/com/xcong/excoin/modules/contract/mapper/ContractHoldOrderMapper.java b/src/main/java/com/xcong/excoin/modules/contract/mapper/ContractHoldOrderMapper.java new file mode 100644 index 0000000..128a1c0 --- /dev/null +++ b/src/main/java/com/xcong/excoin/modules/contract/mapper/ContractHoldOrderMapper.java @@ -0,0 +1,15 @@ +package com.xcong.excoin.modules.contract.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.xcong.excoin.modules.contract.entity.ContractHoldOrderEntity; +import org.apache.ibatis.annotations.Param; + +/** + * @author helius + */ +public interface ContractHoldOrderMapper extends BaseMapper<ContractHoldOrderEntity> { + + IPage<ContractHoldOrderEntity> selectHoldListInPage(@Param("record") ContractHoldOrderEntity entity, Page<ContractHoldOrderEntity> page); +} diff --git a/src/main/java/com/xcong/excoin/modules/contract/mapper/TradeSettingDao.java b/src/main/java/com/xcong/excoin/modules/contract/mapper/TradeSettingDao.java new file mode 100644 index 0000000..52da67e --- /dev/null +++ b/src/main/java/com/xcong/excoin/modules/contract/mapper/TradeSettingDao.java @@ -0,0 +1,21 @@ +package com.xcong.excoin.modules.contract.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.xcong.excoin.modules.contract.entity.PlatformLeverageSettingEntity; +import com.xcong.excoin.modules.contract.entity.PlatformSymbolsSkuEntity; +import com.xcong.excoin.modules.contract.entity.PlatformTradeSettingEntity; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +public interface TradeSettingDao extends BaseMapper<PlatformTradeSettingEntity> { + + PlatformTradeSettingEntity findTradeSetting(); + + PlatformSymbolsSkuEntity findSymbolSkubySymbol(@Param("symbol") String symbol); + + List<PlatformSymbolsSkuEntity> findAllSymbolSkubySymbol(); + + List<PlatformLeverageSettingEntity> findLeverageSetting(); + +} diff --git a/src/main/java/com/xcong/excoin/modules/contract/service/IContractHoldOrderService.java b/src/main/java/com/xcong/excoin/modules/contract/service/IContractHoldOrderService.java new file mode 100644 index 0000000..38a61fc --- /dev/null +++ b/src/main/java/com/xcong/excoin/modules/contract/service/IContractHoldOrderService.java @@ -0,0 +1,15 @@ +package com.xcong.excoin.modules.contract.service; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.IService; +import com.xcong.excoin.common.entity.QueryRequest; +import com.xcong.excoin.modules.contract.entity.ContractHoldOrderEntity; + +/** + * @author wzy + * @date 2020-06-16 + **/ +public interface IContractHoldOrderService extends IService<ContractHoldOrderEntity> { + + IPage<ContractHoldOrderEntity> findHoldList(ContractHoldOrderEntity contractHoldOrderEntity, QueryRequest request); +} diff --git a/src/main/java/com/xcong/excoin/modules/contract/service/impl/ContractHoldOrderServiceImpl.java b/src/main/java/com/xcong/excoin/modules/contract/service/impl/ContractHoldOrderServiceImpl.java new file mode 100644 index 0000000..e995821 --- /dev/null +++ b/src/main/java/com/xcong/excoin/modules/contract/service/impl/ContractHoldOrderServiceImpl.java @@ -0,0 +1,74 @@ +package com.xcong.excoin.modules.contract.service.impl; + +import cn.hutool.core.collection.CollUtil; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.xcong.excoin.common.entity.QueryRequest; +import com.xcong.excoin.common.service.RedisService; +import com.xcong.excoin.common.utils.CacheSettingUtils; +import com.xcong.excoin.common.utils.CoinTypeConvert; +import com.xcong.excoin.modules.agent.entity.MemberEntity; +import com.xcong.excoin.modules.contract.entity.ContractHoldOrderEntity; +import com.xcong.excoin.modules.contract.entity.PlatformTradeSettingEntity; +import com.xcong.excoin.modules.contract.mapper.ContractHoldOrderMapper; +import com.xcong.excoin.modules.contract.service.IContractHoldOrderService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.math.BigDecimal; + +/** + * @author wzy + * @date 2020-06-16 + **/ +@Slf4j +@Service +@RequiredArgsConstructor +public class ContractHoldOrderServiceImpl extends ServiceImpl<ContractHoldOrderMapper, ContractHoldOrderEntity> implements IContractHoldOrderService { + + private final RedisService redisService; + + private final CacheSettingUtils cacheSettingUtils; + + @Override + public IPage<ContractHoldOrderEntity> findHoldList(ContractHoldOrderEntity contractHoldOrderEntity, QueryRequest request) { + Page<ContractHoldOrderEntity> page = new Page<>(request.getPageNum(), request.getPageSize()); + IPage<ContractHoldOrderEntity> list = this.baseMapper.selectHoldListInPage(contractHoldOrderEntity, page); + if (CollUtil.isNotEmpty(list.getRecords())) { + // 计算订单盈亏和回报率 + for (ContractHoldOrderEntity holdOrderEntity : list.getRecords()) { + BigDecimal newPrice = new BigDecimal((String) redisService.get(CoinTypeConvert.convertToKey(holdOrderEntity.getSymbol()))); + BigDecimal lotNumber = cacheSettingUtils.getSymbolSku(holdOrderEntity.getSymbol()); + // 盈亏 + BigDecimal rewardRatio = BigDecimal.ZERO; + // 开多 + if (ContractHoldOrderEntity.OPENING_TYPE_MORE == holdOrderEntity.getOpeningType()) { + // (最新价-开仓价)*规格*张数 + rewardRatio = newPrice.subtract(holdOrderEntity.getOpeningPrice()).multiply(lotNumber).multiply(new BigDecimal(holdOrderEntity.getSymbolCnt())); + // 开空 + } else { + // (开仓价-最新价)*规格*张数 + rewardRatio = holdOrderEntity.getOpeningPrice().subtract(newPrice).multiply(lotNumber).multiply(new BigDecimal(holdOrderEntity.getSymbolCnt())); + } + + if (holdOrderEntity.getIsProfit() == MemberEntity.IS_PROFIT_Y) { + PlatformTradeSettingEntity tradeSettingEntity = cacheSettingUtils.getTradeSetting(); + if (rewardRatio.compareTo(BigDecimal.ZERO) > -1) { + rewardRatio = rewardRatio.multiply(BigDecimal.ONE.subtract(tradeSettingEntity.getProfitParam())); + } else { + rewardRatio = rewardRatio.multiply(BigDecimal.ONE.add(tradeSettingEntity.getProfitParam())); + } + } + + // 回报率 + BigDecimal returnRate = rewardRatio.divide(holdOrderEntity.getBondAmount().subtract(holdOrderEntity.getOpeningFeeAmount()), 8, BigDecimal.ROUND_DOWN); + + holdOrderEntity.setLoseOrProfit(rewardRatio); + holdOrderEntity.setReturnRatio(returnRate); + } + } + return list; + } +} diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index 49ce671..70f014a 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -22,7 +22,7 @@ redis: # Redis数据库索引(默认为 0) - database: 3 + database: 1 # Redis服务器地址 host: 47.114.114.219 # Redis服务器连接端口 diff --git a/src/main/resources/mapper/modules/ContractHoldOrderMapper.xml b/src/main/resources/mapper/modules/ContractHoldOrderMapper.xml new file mode 100644 index 0000000..54d4a9c --- /dev/null +++ b/src/main/resources/mapper/modules/ContractHoldOrderMapper.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> +<mapper namespace="com.xcong.excoin.modules.contract.mapper.ContractHoldOrderMapper"> + + <select id="selectHoldListInPage" resultType="com.xcong.excoin.modules.contract.entity.ContractHoldOrderEntity"> + select * + from contract_hold_order a + inner join member b on a.member_id=b.id + <where> + <if test="record != null"> + <if test="record.inviteId!=null and record.inviteId!=''"> + and find_in_set(#{record.inviteId}, b.referer_ids) + </if> + </if> + </where> + order by a.create_time desc + </select> +</mapper> \ No newline at end of file diff --git a/src/main/resources/mapper/modules/TradeSettingDao.xml b/src/main/resources/mapper/modules/TradeSettingDao.xml new file mode 100644 index 0000000..bda014c --- /dev/null +++ b/src/main/resources/mapper/modules/TradeSettingDao.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" > +<mapper namespace="com.xcong.excoin.modules.contract.mapper.TradeSettingDao"> + + <select id="findTradeSetting" resultType="com.xcong.excoin.modules.contract.entity.PlatformTradeSettingEntity"> + SELECT * FROM platform_trade_setting + </select> + + <select id="findSymbolSkubySymbol" resultType="com.xcong.excoin.modules.contract.entity.PlatformSymbolsSkuEntity"> + select * from platform_symbols_sku + <where> + <if test="symbol!=null and symbol!=''"> + name = #{symbol} + </if> + </where> + </select> + + <select id="findAllSymbolSkubySymbol" resultType="com.xcong.excoin.modules.contract.entity.PlatformSymbolsSkuEntity"> + select * from platform_symbols_sku + </select> + + <select id="findLeverageSetting" resultType="com.xcong.excoin.modules.contract.entity.PlatformLeverageSettingEntity"> + select * from platform_leverage_setting order by value ASC + </select> + +</mapper> diff --git a/src/main/resources/templates/febs/views/modules/contract/hold-list.html b/src/main/resources/templates/febs/views/modules/contract/hold-list.html new file mode 100644 index 0000000..0072890 --- /dev/null +++ b/src/main/resources/templates/febs/views/modules/contract/hold-list.html @@ -0,0 +1,175 @@ +<div class="layui-fluid layui-anim febs-anim" id="febs-user" lay-title="当前持仓"> + <div class="layui-row febs-container"> + <div class="layui-col-md12"> + <div class="layui-card"> + <div class="layui-card-body febs-table-full"> + <form class="layui-form layui-table-form" lay-filter="user-table-form"> + <div class="layui-row"> + <div class="layui-col-md10"> + <div class="layui-form-item"> + <div class="layui-inline"> + <div class="layui-input-inline"> + <input type="text" placeholder="手机号/邮箱/邀请码" name="account" + autocomplete="off" class="layui-input"> + </div> + </div> + <div class="layui-inline"> + <label class="layui-form-label layui-form-label-sm">创建时间</label> + <div class="layui-input-inline"> + <input type="text" name="createTime" id="user-createTime" + class="layui-input"> + </div> + </div> + <div class="layui-inline"> + <label class="layui-form-label layui-form-label-sm">账号类型</label> + <div class="layui-input-inline"> + <select name="accountType"> + <option value=""></option> + <option value="1">测试账号</option> + <option value="2">正常账号</option> + </select> + </div> + </div> + <div class="layui-inline"> + <label class="layui-form-label layui-form-label-sm">账号状态</label> + <div class="layui-input-inline"> + <select name="accountStatus"> + <option value=""></option> + <option value="0">禁用</option> + <option value="1">正常</option> + </select> + </div> + </div> + <div class="layui-inline"> + <label class="layui-form-label layui-form-label-sm">实名状态</label> + <div class="layui-input-inline"> + <select name="certifyStatus"> + <option value=""></option> + <option value="0">未通过</option> + <option value="1">审核中</option> + <option value="2">审核通过</option> + <option value="2">未实名</option> + </select> + </div> + </div> + </div> + </div> + <div class="layui-col-md2 layui-col-sm12 layui-col-xs12 table-action-area"> + <div class="layui-btn layui-btn-sm layui-btn-primary febs-button-blue-plain table-action" + id="query"> + <i class="layui-icon"></i> + </div> + <div class="layui-btn layui-btn-sm layui-btn-primary febs-button-green-plain table-action" + id="reset"> + <i class="layui-icon"></i> + </div> + </div> + </div> + </form> + <table lay-filter="userTable" lay-data="{id: 'userTable'}"></table> + </div> + </div> + </div> + </div> +</div> +<!-- 表格字段状态格式化 start --> +<script type="text/html" id="open-type"> + {{# + var openType = { + 1: {title: '开多', color : 'blue'}, + 2: {title: '开空', color : 'red'} + }[d.openingType]; + }} + <span class="layui-badge febs-bg-{{openType.color}}">{{ openType.title }}</span> +</script> +<!-- 表格字段状态格式化 start --> + +<script data-th-inline="none" type="text/javascript"> + // 引入组件并初始化 + layui.use(['dropdown', 'jquery', 'laydate', 'form', 'table', 'febs', 'treeSelect'], function () { + var $ = layui.jquery, + laydate = layui.laydate, + febs = layui.febs, + form = layui.form, + table = layui.table, + $view = $('#febs-user'), + $query = $view.find('#query'), + $reset = $view.find('#reset'), + $searchForm = $view.find('form'), + sortObject = {field: 'createTime', type: null}, + tableIns, + createTimeFrom, + createTimeTo; + + form.render(); + + // 表格初始化 + initTable(); + + // 时间组件 + laydate.render({ + elem: '#user-createTime', + range: true, + trigger: 'click' + }); + + // 查询按钮 + $query.on('click', function () { + var params = $.extend(getQueryParams(), {field: sortObject.field, order: sortObject.type}); + tableIns.reload({where: params, page: {curr: 1}}); + }); + + // 刷新按钮 + $reset.on('click', function () { + $searchForm[0].reset(); + sortObject.type = 'null'; + createTimeTo = null; + createTimeFrom = null; + tableIns.reload({where: getQueryParams(), page: {curr: 1}, initSort: sortObject}); + }); + + function initTable() { + tableIns = febs.table.init({ + elem: $view.find('table'), + id: 'userTable', + url: ctx + 'order/getHoldList', + cols: [[ + {type: 'checkbox'}, + {field: 'orderNo', title: '订单编号', minWidth: 150, align: 'center'}, + {field: 'symbol', title: '币种', minWidth: 100, align: 'center'}, + {field: 'refererId', title: '上级UID', minWidth: 100, align: 'center'}, + {field: 'telphone', title: '联系方式', minWidth: 130, align: 'center'}, + {field: 'email', title: '邮箱', minWidth: 100, align: 'center'}, + {title: '开仓类型', templet: '#open-type', minWidth: 100, align: 'center'}, + {field: 'leverRatio', title: '杠杆倍率', minWidth: 100, align: 'center'}, + {field: 'openingPrice', title: '开仓均价', minWidth: 120, align: 'center'}, + {field: 'symbolCnt', title: '持仓数', minWidth: 100, align: 'center'}, + {field: 'symbolCntSale', title: '可平数', minWidth: 100, align: 'center'}, + {field: 'forceClosingPrice', title: '预估强平价', minWidth: 130, align: 'center'}, + {field: 'bondAmount', title: '保证金', minWidth: 130, align: 'center'}, + {field: 'createTime', title: '开仓时间', minWidth: 160, align: 'center'}, + {field: 'loseOrProfit', title: '盈亏', minWidth: 140, align: 'center', fixed : "right"}, + {field: 'returnRatio', title: '回报率', minWidth: 140, align: 'center', fixed : "right"}, + ]] + }); + } + + // 获取查询参数 + function getQueryParams() { + var createTime = $searchForm.find('input[name="createTime"]').val(); + if (createTime) { + createTimeFrom = createTime.split(' - ')[0]; + createTimeTo = createTime.split(' - ')[1]; + } + return { + startTime: createTimeFrom, + endTime: createTimeTo, + account: $searchForm.find('input[name="account"]').val().trim(), + accountStatus: $searchForm.find("select[name='accountStatus']").val(), + accountType: $searchForm.find("select[name='accountType']").val(), + certifyStatus: $searchForm.find("select[name='certifyStatus']").val(), + invalidate_ie_cache: new Date() + }; + } + }) +</script> \ No newline at end of file -- Gitblit v1.9.1