package com.nq.service.impl;
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.nq.common.ServerResponse;
|
import com.nq.dao.*;
|
import com.nq.enums.EStockType;
|
import com.nq.enums.EUserAssets;
|
import com.nq.enums.TradeType;
|
import com.nq.pojo.*;
|
import com.nq.service.IUserAssetsServices;
|
import com.nq.service.TransactionLogService;
|
import com.nq.utils.KeyUtils;
|
import lombok.extern.slf4j.Slf4j;
|
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.*;
|
|
/**
|
* 用户资产
|
*/
|
@Slf4j
|
@Service
|
public class UserAssetsServices extends ServiceImpl<UserAssetsMapper, UserAssets> implements IUserAssetsServices {
|
|
@Resource
|
UserAssetsMapper userAssetsMapper;
|
|
@Resource
|
MoneyLogMapper moneyLogMapper;
|
|
@Autowired
|
UserRechargeServiceImpl userRechargeService;
|
|
@Autowired
|
UserWithdrawServiceImpl withdrawService;
|
|
@Resource
|
UserRechargeMapper userRechargeMapper;
|
|
@Resource
|
UserMapper userMapper;
|
|
@Autowired
|
UserPositionMapper userPositionMapper;
|
|
@Autowired
|
StockConfigMapper stockConfigMapper;
|
|
@Autowired
|
TransactionLogService transactionLogService;
|
@Override
|
public UserAssets assetsByTypeAndUserId(String accetType, Integer userId) {
|
if(accetType.equals("SZHB")){
|
accetType = "US";
|
}
|
QueryWrapper<UserAssets> queryWrapper = new QueryWrapper<>();
|
queryWrapper.eq("accect_type",accetType);
|
queryWrapper.eq("user_id",userId);
|
UserAssets userAssets = userAssetsMapper.selectOne(queryWrapper);
|
if(userAssets == null){
|
userAssets = new UserAssets();
|
userAssets.setAccectType(accetType);
|
userAssets.setUserId(userId);
|
userAssetsMapper.insert(userAssets);
|
}
|
userAssets = userAssetsMapper.selectOne(queryWrapper);
|
return userAssets;
|
}
|
|
@Override
|
public ServerResponse updateUserAssets(Integer id, String amt, String type, String accectType) {
|
UserAssets userAssets = userAssetsMapper.selectOne(new LambdaQueryWrapper<>(UserAssets.class)
|
.eq(UserAssets::getId,id)
|
.eq(UserAssets::getAccectType,accectType)
|
);
|
UserPosition userPosition = userPositionMapper.selectOne(new LambdaQueryWrapper<UserPosition>().gt(UserPosition::getAmountToBeCovered, BigDecimal.ZERO).eq(UserPosition::getUserId,userAssets.getUserId()));
|
// 0 入款 1是扣钱 2 是充值 3 是提币
|
BigDecimal bigAmt = new BigDecimal(amt);
|
if(type.equals("0") || type.equals("1")){
|
if(type.equals("1")){
|
bigAmt = bigAmt.negate();
|
}
|
if(type.equals("0")){
|
if(userAssets.getAmountToBeCovered().compareTo(BigDecimal.ZERO) > 0){
|
BigDecimal availableBalance = bigAmt.subtract(userAssets.getAmountToBeCovered());
|
availableBalance = availableBalance.subtract(userAssets.getHandlingChargeWritten());
|
if(availableBalance.compareTo(BigDecimal.ZERO) >= 0){
|
userAssets.setAvailableBalance(userAssets.getAvailableBalance().add(availableBalance));
|
userAssets.setFreezeMoney(userAssets.getFreezeMoney().add(userAssets.getAmountToBeCovered()));
|
userAssets.setAmountToBeCovered(BigDecimal.ZERO);
|
userAssets.setHandlingChargeWritten(BigDecimal.ZERO);
|
if(null != userPosition){
|
userPosition.setAmountToBeCovered(userAssets.getAmountToBeCovered());
|
}
|
}else{
|
BigDecimal amountToBeCovered = userAssets.getAmountToBeCovered().subtract(bigAmt);
|
userAssets.setFreezeMoney(userAssets.getFreezeMoney().add(bigAmt));
|
userAssets.setAmountToBeCovered(amountToBeCovered);
|
if(null != userPosition){
|
userPosition.setAmountToBeCovered(userAssets.getAmountToBeCovered());
|
}
|
}
|
}else{
|
userAssets.setAvailableBalance(userAssets.getAvailableBalance().add(bigAmt));
|
}
|
}else{
|
if(userAssets.getAvailableBalance().compareTo(BigDecimal.ZERO) <= 0){
|
return ServerResponse.createByErrorMsg("客户账户余额为0");
|
}else if(userAssets.getAvailableBalance().subtract(bigAmt.abs()).compareTo(BigDecimal.ZERO) < 0){
|
return ServerResponse.createByErrorMsg("客户账户余额不足扣款");
|
}
|
userAssets.setAvailableBalance(userAssets.getAvailableBalance().add(bigAmt));
|
}
|
if(null != userPosition){
|
userPositionMapper.updateById(userPosition);
|
}
|
if( userAssetsMapper.updateById(userAssets)>0){
|
// saveUserRecharge(userAssets.getUserId(),bigAmt);
|
return ServerResponse.createBySuccess();
|
}else{
|
return ServerResponse.createByErrorMsg("修改金额失败");
|
}
|
}else{
|
if(type.equals("2")){
|
return userRechargeService.createOrder(accectType,userAssets.getUserId(),1,bigAmt.intValue(),"1");
|
}else{
|
return ServerResponse.createBySuccess();
|
}
|
}
|
}
|
|
|
@Override
|
public List<UserAssets> assetsByUserId(Integer userId) {
|
QueryWrapper<UserAssets> queryWrapper = new QueryWrapper<>();
|
queryWrapper.eq("user_id",userId);
|
return userAssetsMapper.selectList(queryWrapper);
|
}
|
|
@Override
|
public BigDecimal getAvailableBalance(String accetType, Integer userId) {
|
if(accetType.equals("SZHB")){
|
accetType = "US";
|
}
|
return assetsByTypeAndUserId(accetType,userId).getAvailableBalance();
|
}
|
|
|
@Override
|
public Boolean availablebalanceChange(String accetType, Integer userId, EUserAssets eUserAssets, BigDecimal amount, String desc, String descType) {
|
|
UserAssets userAssets = assetsByTypeAndUserId(accetType,userId);
|
UserPosition userPosition = userPositionMapper.selectOne(new LambdaQueryWrapper<UserPosition>().gt(UserPosition::getAmountToBeCovered, BigDecimal.ZERO).eq(UserPosition::getUserId,userAssets.getUserId()));
|
String type = eUserAssets.getDesc();
|
String before = userAssets.getAvailableBalance().toString();
|
String accectType = userAssets.getAccectType();
|
if(Objects.equals(eUserAssets.getCode(), EUserAssets.BUY.getCode())){
|
userAssets.setAvailableBalance(userAssets.getAvailableBalance().add(amount));
|
userAssets.setFreezeMoney(userAssets.getFreezeMoney().add(amount.negate()));
|
}else if(Objects.equals(eUserAssets.getCode(), EUserAssets.CLOSE_POSITION.getCode())){
|
userAssets.setAvailableBalance(userAssets.getAvailableBalance().add(amount));
|
extracted(amount, userAssets);
|
}else if(Objects.equals(eUserAssets.getCode(), EUserAssets.CLOSE_POSITION_RETURN_SECURITY_DEPOSIT.getCode())){
|
if(userAssets.getAmountToBeCovered().compareTo(BigDecimal.ZERO) > 0){
|
BigDecimal availableBalance = amount.subtract(userAssets.getAmountToBeCovered());
|
availableBalance = availableBalance.subtract(userAssets.getHandlingChargeWritten());
|
if(availableBalance.compareTo(BigDecimal.ZERO) >= 0){
|
userAssets.setAvailableBalance(userAssets.getAvailableBalance().add(availableBalance));
|
userAssets.setAmountToBeCovered(BigDecimal.ZERO);
|
userAssets.setHandlingChargeWritten(BigDecimal.ZERO);
|
}else{
|
BigDecimal amountToBeCovered = userAssets.getAmountToBeCovered().subtract(amount);
|
userAssets.setAmountToBeCovered(amountToBeCovered);
|
}
|
}else{
|
userAssets.setAvailableBalance(userAssets.getAvailableBalance().add(amount));
|
}
|
userAssets.setFreezeMoney(userAssets.getFreezeMoney().subtract(amount));
|
}else if(Objects.equals(eUserAssets.getCode(), EUserAssets.THE_DEPOSIT_WILL_BE_RETURNED_IF_THE_ORDER_IS_CANCELLED.getCode())){
|
if(userAssets.getAmountToBeCovered().compareTo(BigDecimal.ZERO) > 0){
|
BigDecimal availableBalance = amount.subtract(userAssets.getAmountToBeCovered());
|
availableBalance = availableBalance.subtract(userAssets.getHandlingChargeWritten());
|
if(availableBalance.compareTo(BigDecimal.ZERO) >= 0){
|
userAssets.setAvailableBalance(userAssets.getAvailableBalance().add(availableBalance));
|
userAssets.setAmountToBeCovered(BigDecimal.ZERO);
|
userAssets.setHandlingChargeWritten(BigDecimal.ZERO);
|
}else{
|
BigDecimal amountToBeCovered = userAssets.getAmountToBeCovered().subtract(amount);
|
userAssets.setAmountToBeCovered(amountToBeCovered);
|
}
|
}else{
|
userAssets.setAvailableBalance(userAssets.getAvailableBalance().add(amount));
|
}
|
userAssets.setFreezeMoney(userAssets.getFreezeMoney().subtract(amount));
|
}else if(Objects.equals(eUserAssets.getCode(), EUserAssets.CALCULATE_PROFIT_AND_LOSS.getCode())){
|
extracted(amount, userAssets);
|
}else if(Objects.equals(eUserAssets.getCode(), EUserAssets.TRANSFER.getCode())){
|
userAssets.setAvailableBalance(userAssets.getAvailableBalance().add(amount));
|
eUserAssets.setDesc(desc);
|
}else if(Objects.equals(eUserAssets.getCode(), EUserAssets.TOP_UP.getCode())){
|
if(userAssets.getAmountToBeCovered().compareTo(BigDecimal.ZERO) > 0){
|
BigDecimal availableBalance = amount.subtract(userAssets.getAmountToBeCovered());
|
availableBalance = availableBalance.subtract(userAssets.getHandlingChargeWritten());
|
if(availableBalance.compareTo(BigDecimal.ZERO) >= 0){
|
userAssets.setAvailableBalance(userAssets.getAvailableBalance().add(availableBalance));
|
userAssets.setFreezeMoney(userAssets.getFreezeMoney().add(userAssets.getAmountToBeCovered()));
|
userAssets.setAmountToBeCovered(BigDecimal.ZERO);
|
userAssets.setHandlingChargeWritten(BigDecimal.ZERO);
|
}else{
|
userAssets.setFreezeMoney(userAssets.getFreezeMoney().add(amount));
|
userAssets.setHandlingChargeWritten(BigDecimal.ZERO);
|
userAssets.setAmountToBeCovered(availableBalance.negate());
|
}
|
}else{
|
userAssets.setAvailableBalance(userAssets.getAvailableBalance().add(amount));
|
}
|
}else if(Objects.equals(eUserAssets.getCode(), EUserAssets.WITHDRAW.getCode())){
|
userAssets.setAvailableBalance(userAssets.getAvailableBalance().add(amount));
|
userAssets.setFreezeMoney(userAssets.getFreezeMoney().add(amount.abs()));
|
}else if(Objects.equals(eUserAssets.getCode(), EUserAssets.HANDLING_CHARGE.getCode())){
|
if(userAssets.getAvailableBalance().compareTo(amount.abs()) >= 0){
|
userAssets.setAvailableBalance(userAssets.getAvailableBalance().add(amount.negate()));
|
}else {
|
userAssets.setHandlingChargeWritten(userAssets.getHandlingChargeWritten().add(amount.abs()));
|
}
|
userAssets.setHandlingCharge(userAssets.getHandlingCharge().add(amount.abs()));
|
|
extracted(amount.negate(),userAssets);
|
}else if(Objects.equals(eUserAssets.getCode(), EUserAssets.CONSTRAINT_CLOSE_POSITION.getCode())){
|
userAssets.setFreezeMoney(userAssets.getFreezeMoney().subtract(amount));
|
if(userAssets.getIsZf() == 0){
|
userAssets.setCumulativeProfitAndLoss(userAssets.getCumulativeProfitAndLoss().subtract(amount));
|
}else{
|
userAssets.setCumulativeProfitAndLoss(userAssets.getCumulativeProfitAndLoss().add(amount));
|
}
|
extracted(userAssets);
|
}else if(Objects.equals(eUserAssets.getCode(), EUserAssets.CALL.getCode())){
|
userAssets.setFreezeMoney(userAssets.getFreezeMoney().subtract(amount));
|
extracted(amount, userAssets);
|
}
|
|
if(null != userPosition){
|
userPosition.setAmountToBeCovered(userAssets.getAmountToBeCovered().add(userAssets.getHandlingChargeWritten()));
|
userPositionMapper.updateById(userPosition);
|
}
|
String after = userAssets.getAvailableBalance().toString();
|
MoneyLog moneyLog = new MoneyLog();
|
moneyLog.setDescs(eUserAssets.getDesc());
|
moneyLog.setBeFore(before);
|
moneyLog.setAfter(after);
|
moneyLog.setAmount(amount.toString());
|
moneyLog.setAccectType(accectType);
|
moneyLog.setType(eUserAssets.getCode());
|
moneyLog.setUserId(userId+"");
|
moneyLog.setSymbol(EStockType.getEStockTypeByCode(accetType).getSymbol());
|
moneyLog.setCreateTime(new Date());
|
moneyLogMapper.insert(moneyLog);
|
int update = userAssetsMapper.updateById(userAssets);
|
if(update > 0){
|
if(Objects.equals(eUserAssets.getCode(), EUserAssets.HANDLING_CHARGE.getCode())){
|
amount = amount.negate();
|
}
|
transactionLogService.add(userId, eUserAssets.getDesc(),amount.toString(),eUserAssets.getDesc());
|
return true;
|
}
|
return false;
|
}
|
|
@Override
|
@Transactional
|
public ServerResponse transfer(Integer userId, String disbursementAccount, String depositAccount, String amt, HttpServletRequest request) {
|
// 参数校验
|
ServerResponse paramCheckResponse = checkParameters(userId, disbursementAccount, depositAccount, amt, request);
|
if (paramCheckResponse != null) {
|
return paramCheckResponse;
|
}
|
|
// 转账金额合法性检查
|
BigDecimal transferAmount = validateTransferAmount(amt, request);
|
if (transferAmount == null) {
|
return ServerResponse.createByErrorMsg("无效的转账金额", request);
|
}
|
|
// 查询转出账户和转入账户的资产信息
|
UserAssets disbursement = getUserAssets(userId, disbursementAccount);
|
UserAssets deposit = getUserAssets(userId, depositAccount);
|
|
// 账户检查
|
if (disbursement == null) {
|
return ServerResponse.createByErrorMsg("转出账户不存在", request);
|
}
|
if (deposit == null) {
|
return ServerResponse.createByErrorMsg("转入账户不存在", request);
|
}
|
|
// 检查转出账户余额是否足够
|
if (isBalanceSufficient(disbursement.getAvailableBalance(), transferAmount)) {
|
return ServerResponse.createByErrorMsg("转出账户余额不足", request);
|
}
|
|
// 执行转账操作
|
try {
|
synchronized (userId){
|
performTransfer(disbursementAccount,disbursement, deposit, transferAmount);
|
}
|
return ServerResponse.createBySuccess("划转成功", request);
|
} catch (Exception e) {
|
log.error("划转失败: " + e.getMessage(), e);
|
return ServerResponse.createByErrorMsg("划转失败", request);
|
}
|
}
|
|
// 参数校验
|
private ServerResponse checkParameters(Integer userId, String disbursementAccount, String depositAccount, String amt, HttpServletRequest request) {
|
if (userId == null || disbursementAccount == null || depositAccount == null || amt == null) {
|
return ServerResponse.createByErrorMsg("输入参数不能为空", request);
|
}
|
return null;
|
}
|
|
// 转账金额校验
|
private BigDecimal validateTransferAmount(String amt, HttpServletRequest request) {
|
try {
|
BigDecimal transferAmount = BigDecimal.valueOf(Double.valueOf(amt));
|
if (transferAmount.compareTo(BigDecimal.ZERO) <= 0) {
|
ServerResponse.createByErrorMsg("转账金额必须大于零", request);
|
return null;
|
}
|
return transferAmount;
|
} catch (NumberFormatException e) {
|
return null;
|
}
|
}
|
|
// 获取账户资产信息
|
private UserAssets getUserAssets(Integer userId, String accountType) {
|
return userAssetsMapper.selectOne(new LambdaQueryWrapper<>(UserAssets.class)
|
.eq(UserAssets::getAccectType, accountType)
|
.eq(UserAssets::getUserId, userId));
|
}
|
|
// 判断余额是否足够
|
private boolean isBalanceSufficient(BigDecimal balance, BigDecimal transferAmount) {
|
return balance.compareTo(transferAmount) < 0;
|
}
|
|
// 执行转账操作
|
private void performTransfer(String disbursementAccount,UserAssets disbursement, UserAssets deposit, BigDecimal transferAmount) {
|
StockConfig stockConfig = stockConfigMapper.selectOne(new LambdaQueryWrapper<StockConfig>().eq(StockConfig::getCKey, "usdt_parities"));
|
if(disbursementAccount.equals("USD")){
|
// 更新转入账户余额
|
deposit.setAvailableBalance(deposit.getAvailableBalance().add(transferAmount.multiply(new BigDecimal(stockConfig.getCValue()))));
|
userAssetsMapper.updateById(deposit);
|
// 更新转出账户余额
|
disbursement.setAvailableBalance(disbursement.getAvailableBalance().subtract(transferAmount));
|
userAssetsMapper.updateById(disbursement);
|
}else if(disbursementAccount.equals("ST")){
|
// 更新转入账户余额
|
deposit.setAvailableBalance(deposit.getAvailableBalance().add(transferAmount.divide(new BigDecimal(stockConfig.getCValue()))));
|
userAssetsMapper.updateById(deposit);
|
// 更新转出账户余额
|
disbursement.setAvailableBalance(disbursement.getAvailableBalance().subtract(transferAmount));
|
userAssetsMapper.updateById(disbursement);
|
}
|
}
|
|
//只要涉及到cumulativeProfitAndLoss变动重新设置状态
|
private static void extracted(UserAssets userAssets) {
|
if(userAssets.getCumulativeProfitAndLoss().compareTo(BigDecimal.ZERO) >= 0){
|
userAssets.setIsZf(0);
|
}else{
|
userAssets.setIsZf(1);
|
userAssets.setCumulativeProfitAndLoss(userAssets.getCumulativeProfitAndLoss().abs());
|
}
|
}
|
|
private static void extracted(BigDecimal amount, UserAssets userAssets) {
|
if(userAssets.getIsZf() == 1){
|
userAssets.setCumulativeProfitAndLoss(userAssets.getCumulativeProfitAndLoss().negate());
|
}
|
if(userAssets.getIsZf() == 0){
|
if(amount.compareTo(BigDecimal.ZERO) >= 0){
|
userAssets.setCumulativeProfitAndLoss(userAssets.getCumulativeProfitAndLoss().add(amount.abs()));
|
}else{
|
userAssets.setCumulativeProfitAndLoss(userAssets.getCumulativeProfitAndLoss().subtract(amount.abs()));
|
}
|
}else{
|
if(amount.compareTo(BigDecimal.ZERO) >= 0){
|
userAssets.setCumulativeProfitAndLoss(userAssets.getCumulativeProfitAndLoss().add(amount.abs()));
|
}else{
|
userAssets.setCumulativeProfitAndLoss(userAssets.getCumulativeProfitAndLoss().subtract(amount.abs()));
|
}
|
}
|
extracted(userAssets);
|
}
|
|
}
|