zyy
2026-01-21 5ed78846f18a51a66869b44491a53065b058549d
新增可取资金
6 files modified
4 files added
234 ■■■■■ changed files
.idea/jarRepositories.xml 5 ●●●●● patch | view | raw | blame | history
src/main/java/com/nq/dao/FundFlowMapper.java 11 ●●●●● patch | view | raw | blame | history
src/main/java/com/nq/pojo/FundFlow.java 25 ●●●●● patch | view | raw | blame | history
src/main/java/com/nq/pojo/StockSubscribe.java 3 ●●●●● patch | view | raw | blame | history
src/main/java/com/nq/service/impl/UserPositionServiceImpl.java 20 ●●●●● patch | view | raw | blame | history
src/main/java/com/nq/service/impl/UserServiceImpl.java 3 ●●●●● patch | view | raw | blame | history
src/main/java/com/nq/service/impl/UserWithdrawServiceImpl.java 31 ●●●●● patch | view | raw | blame | history
src/main/java/com/nq/utils/DateTimeUtil.java 35 ●●●●● patch | view | raw | blame | history
src/main/java/com/nq/utils/task/user/FundFlowTask.java 94 ●●●●● patch | view | raw | blame | history
src/main/resources/mapper/FundFlowMapper.xml 7 ●●●●● patch | view | raw | blame | history
.idea/jarRepositories.xml
@@ -16,5 +16,10 @@
      <option name="name" value="JBoss Community repository" />
      <option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
    </remote-repository>
    <remote-repository>
      <option name="id" value="central" />
      <option name="name" value="Central Repository" />
      <option name="url" value="https://maven.aliyun.com/repository/public" />
    </remote-repository>
  </component>
</project>
src/main/java/com/nq/dao/FundFlowMapper.java
New file
@@ -0,0 +1,11 @@
package com.nq.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.nq.pojo.FundFlow;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface FundFlowMapper extends BaseMapper<FundFlow> {
}
src/main/java/com/nq/pojo/FundFlow.java
New file
@@ -0,0 +1,25 @@
package com.nq.pojo;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.math.BigDecimal;
import java.util.Date;
@TableName("fund_flow")
@Data
public class FundFlow {
    @TableId(type = IdType.AUTO,value = "id")
    private Integer id;
    private Integer userId; // 用户ID
    private BigDecimal amount; //待转提现金额(待结转总额)
    private BigDecimal usedAmount; // 该资金已被用金额(初始0)
    private BigDecimal realAmount; //实际转结金额
    private Date withdrawDate;  // 可提现日期(T+1)
    private Integer status; // 0=待结转,1=已结转,2=已用完(无剩余)
    private Date createTime;
}
src/main/java/com/nq/pojo/StockSubscribe.java
@@ -33,6 +33,9 @@
    private String code;
    /**
     * 类型 sh sz hk us
     * sh 沪
     * sz 深
     * bj 京
     */
    private String stockType;
    /**
src/main/java/com/nq/service/impl/UserPositionServiceImpl.java
@@ -106,6 +106,8 @@
    StockDzMapper stockDzMapper;
    @Autowired
    StockVipMapper stockVipMapper;
    @Autowired
    FundFlowMapper fundFlowMapper;
    @Transactional
@@ -779,6 +781,8 @@
        BigDecimal reckon_all = user_all_amt.add(all_profit);
        //修改用戶可用余額=當前可用余額+總盈虧+買入總金額+追加保證金
        BigDecimal reckon_enable = user_enable_amt.add(all_profit).add(freez_amt).add(userPosition.getMarginAdd());
        //锁定提现金额
        BigDecimal lockAmount = reckon_enable.subtract(user_enable_amt);
        log.info("用戶平倉後的總資金  = {} , 可用資金 = {}", reckon_all, reckon_enable);
        user.setUserAmt(reckon_all);
@@ -790,6 +794,18 @@
            log.error("用戶平倉】修改用戶金額出錯");
            throw new Exception("用戶平倉】修改用戶金額出錯");
        }
        if (lockAmount.compareTo(BigDecimal.ZERO) > 0) {
            Date date = new Date();
            FundFlow fundFlow = new FundFlow();
            fundFlow.setUserId(userPosition.getUserId());
            fundFlow.setAmount(lockAmount);
            fundFlow.setUsedAmount(BigDecimal.ZERO);
            fundFlow.setWithdrawDate(DateTimeUtil.addDayAndGetZeroTime(date, 1));
            fundFlow.setStatus(0);
            fundFlow.setCreateTime(date);
            fundFlowMapper.insert(fundFlow);
        }
        UserCashDetail ucd = new UserCashDetail();
        ucd.setPositionId(userPosition.getId());
@@ -1985,6 +2001,10 @@
            userPosition.setStockCode(userStockSubscribe.getNewCode());
            userPosition.setStockName(userStockSubscribe.getNewName());
            userPosition.setStockGid(stockSubscribe.getStockType() + userStockSubscribe.getNewCode());
            Stock stock = stockMapper.selectOne(new QueryWrapper<Stock>().eq("stock_code", userStockSubscribe.getNewCode()));
            if (stock != null) {
                userPosition.setStockGid(stock.getStockGid());
            }
            userPosition.setBuyOrderId(GeneratePosition.getPositionId());
            userPosition.setBuyOrderTime(new Date());
src/main/java/com/nq/service/impl/UserServiceImpl.java
@@ -1528,9 +1528,11 @@
        BigDecimal sh_amt = user.getEnableAmt();
        BigDecimal sh_amt_back = new BigDecimal("0");
        BigDecimal enaleWithdrawAmt = user.getEnaleWithdrawAmt();
        //0 加钱  1 减钱 2虚拟加钱
        if (direction.intValue() == 0||direction.intValue()==2) {
            sh_amt_back = sh_amt.add(new BigDecimal(amt));
            enaleWithdrawAmt  = enaleWithdrawAmt.add(new BigDecimal(amt));
        } else if (direction.intValue() == 1) {
            if (sh_amt.compareTo(new BigDecimal(amt)) == -1) {
@@ -1541,6 +1543,7 @@
            return ServerResponse.createByErrorMsg("不存在此操作");
        }
        user.setEnableAmt(sh_amt_back);
        user.setEnaleWithdrawAmt(enaleWithdrawAmt);
//        BigDecimal hk_amt = user.getHkAmt();
//
src/main/java/com/nq/service/impl/UserWithdrawServiceImpl.java
@@ -132,7 +132,9 @@
            SiteSetting siteSetting = this.iSiteSettingService.getSiteSetting();
            if ((new BigDecimal(amt)).compareTo(new BigDecimal(siteSetting.getWithMinAmt().intValue())) == -1) {
            BigDecimal outAmt = new BigDecimal(amt);
            if (outAmt.compareTo(new BigDecimal(siteSetting.getWithMinAmt().intValue())) == -1) {
                return ServerResponse.createByErrorMsg("出金金额不得低于" + siteSetting.getWithMinAmt() + "元");
@@ -171,17 +173,24 @@
            //可取港币资金
            BigDecimal hkAmt=user.getEnaleWithdrawAmt();
            int compareAmt = hkAmt.compareTo(new BigDecimal(amt));
            BigDecimal userAmt=user.getEnableAmt();
            int compareAmt = hkAmt.compareTo(outAmt);
            if (compareAmt == -1) {
                return ServerResponse.createByErrorMsg("提现失败,用户可取港币资金不足");
                return ServerResponse.createByErrorMsg("提现失败,用户可取资金不足");
            }
            BigDecimal reckon_hkAmt = hkAmt.subtract(new BigDecimal(amt));
            if (userAmt.compareTo(outAmt) < 0) {
                return ServerResponse.createByErrorMsg("提现失败,用户可用资金不足");
            }
            BigDecimal reckon_hkAmt = hkAmt.subtract(outAmt);
            user.setEnaleWithdrawAmt(reckon_hkAmt);
            user.setEnableAmt(userAmt.subtract(outAmt));
            log.info("提现前,港币金额={},提现后,港币金额={}",hkAmt,reckon_hkAmt);
@@ -208,7 +217,7 @@
            userWithdraw.setAgentId(user.getAgentId());
            userWithdraw.setWithAmt(new BigDecimal(amt));
            userWithdraw.setWithAmt(outAmt);
            userWithdraw.setApplyTime(new Date());
@@ -223,7 +232,7 @@
            userWithdraw.setWithStatus(Integer.valueOf(0));
            BigDecimal withfee = siteSetting.getWithFeePercent().multiply(new BigDecimal(amt)).add(new BigDecimal(siteSetting.getWithFeeSingle().intValue()));
            BigDecimal withfee = siteSetting.getWithFeePercent().multiply(outAmt).add(new BigDecimal(siteSetting.getWithFeeSingle().intValue()));
            //userWithdraw.setWithFee(withfee);
@@ -448,12 +457,14 @@
            }
            //计算返还的总港币金额
            BigDecimal hkAmt = user.getHkAmt().add(userWithdraw.getWithAmt());
            //计算返还的可取金额
            BigDecimal hkAmt = user.getEnaleWithdrawAmt().add(userWithdraw.getWithAmt());
            log.info("管理员确认提现订单失败,返还用户 {} 总资金,原金额 = {} , 返还后 = {}", new Object[]{user.getId(), user.getHkAmt(), hkAmt});
            log.info("管理员确认提现订单失败,返还用户 {} 可取资金,原金额 = {} , 返还后 = {}", new Object[]{user.getId(), user.getEnaleWithdrawAmt(), hkAmt});
            user.setHkAmt(hkAmt);
            user.setEnaleWithdrawAmt(hkAmt);
            user.setEnableAmt(user.getEnableAmt().add(userWithdraw.getWithAmt()));
            int updateCount = this.userMapper.updateByPrimaryKeySelective(user);
            if (updateCount > 0) {
src/main/java/com/nq/utils/DateTimeUtil.java
@@ -224,6 +224,25 @@
        return cal.getTime();
    }
    // 新增核心方法:指定日期增加天数后,获取当天0点日期(清空时分秒/毫秒)
    public static Date addDayAndGetZeroTime(Date date, int num) {
        if (date == null) {
            return null;
        }
        Calendar cal = Calendar.getInstance();
        // 1. 先设置原始日期,增加指定天数
        cal.setTime(date);
        cal.add(Calendar.DATE, num);
        // 2. 关键:将时分秒、毫秒全部置为0,只保留日期的0点
        cal.set(Calendar.HOUR_OF_DAY, 0); // 24小时制的小时置0(区别于HOUR(12小时制))
        cal.set(Calendar.MINUTE, 0);      // 分钟置0
        cal.set(Calendar.SECOND, 0);      // 秒置0
        cal.set(Calendar.MILLISECOND, 0); // 毫秒置0(避免微小时间差)
        return cal.getTime();
    }
    //获取当前时间 判断是否是周六日 如果是周六日 则获取周五的时间
    public static String getWeekDay() {
        Calendar cal = Calendar.getInstance();
@@ -238,18 +257,8 @@
    public static void main(String[] args) {
        String DateStr = "2023-03-09 00:00:00";
        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            Date dateTime1 = dateFormat.parse(DateStr);
            System.out.println("dateTime1.getTime()=" + dateTime1.getTime());
            System.out.println("系统=" + DateTimeUtil.getCurrentDate().getTime());
            System.out.println("系统=" + DateTimeUtil.dateToStr(DateTimeUtil.getCurrentDate(), "yyyy-MM-dd HH:mm:ss"));
            System.out.println(DateTimeUtil.getCurrentDate().getTime() < dateTime1.getTime());
        } catch (ParseException e) {
            e.printStackTrace();
        }
        Date date = new Date();
        Date newDate = addDayAndGetZeroTime(date, 1);
        System.out.println(newDate);
    }
}
src/main/java/com/nq/utils/task/user/FundFlowTask.java
New file
@@ -0,0 +1,94 @@
package com.nq.utils.task.user;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.PageInfo;
import com.nq.common.ServerResponse;
import com.nq.dao.FundFlowMapper;
import com.nq.dao.UserMapper;
import com.nq.pojo.FundFlow;
import com.nq.pojo.StockSubscribe;
import com.nq.pojo.User;
import com.nq.service.IUserService;
import com.nq.utils.DateTimeUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
@Component
public class FundFlowTask {
    @Autowired
    private FundFlowMapper fundFlowMapper;
    @Autowired
    UserMapper userMapper;
    private static final Logger log = LoggerFactory.getLogger(FundFlowTask.class);
    /**
     * 第二天锁定金额转结可取
     */
    //@Scheduled(cron = "0 1 0 * * ?")
    @Scheduled(cron = "0 */5 * * * *")
    public void flowTask(){
        try {
            QueryWrapper<FundFlow> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("status", 0);
            queryWrapper.le("withdraw_date", DateTimeUtil.dateToStr1(new Date())).orderByAsc("withdraw_date");
            List<FundFlow> fundFlowList = fundFlowMapper.selectList(queryWrapper);
            if (fundFlowList.isEmpty()){
                log.info("==flowTask===无待转结数据");
                return;
            }
            fundFlowList.forEach(fundFlow -> {
                BigDecimal amount = fundFlow.getAmount();
                BigDecimal usedAmount = fundFlow.getUsedAmount();
                //待转>0 & >已被使用
                if (amount.compareTo(BigDecimal.ZERO) > 0
                        && amount.compareTo(usedAmount) > 0) {
                    User user = this.userMapper.selectByPrimaryKey(fundFlow.getUserId());
                    if(user != null){
                        BigDecimal eWithdrawAmt =user.getEnaleWithdrawAmt();
                        BigDecimal userAmt =user.getEnableAmt().subtract(eWithdrawAmt);
                        if (userAmt.compareTo(BigDecimal.ZERO) == 0){
                            fundFlow.setStatus(2);
                            log.info("==flowTask==id{}=用户资金已用完无法转结", fundFlow.getId());
                        } else {
                            //用户资金足够转结
                            if (userAmt.compareTo(amount) >= 0) {
                                fundFlow.setStatus(1);
                                fundFlow.setRealAmount(amount);
                                user.setEnaleWithdrawAmt(eWithdrawAmt.add(amount));
                                log.info("==flowTask==id{}=用户资金足够,转结{}", fundFlow.getId(), fundFlow.getAmount());
                            } else {
                                fundFlow.setStatus(1);
                                user.setEnaleWithdrawAmt(eWithdrawAmt.add(userAmt));
                                //已使用
                                BigDecimal usedAmt = amount.subtract(userAmt);
                                fundFlow.setUsedAmount(usedAmount.add(usedAmt));
                                fundFlow.setRealAmount(userAmt);
                                log.info("==flowTask==id{}=用户资金不足,转结{},已使用{}", fundFlow.getId(), userAmt, fundFlow.getUsedAmount());
                            }
                        }
                        userMapper.updateByPrimaryKeySelective(user);
                        fundFlowMapper.updateById(fundFlow);
                    }
                }
            });
        }catch (Exception e){
            log.error(e.getMessage(), e);
        }
    }
}
src/main/resources/mapper/FundFlowMapper.xml
New file
@@ -0,0 +1,7 @@
<?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.nq.dao.FundFlowMapper" >
</mapper>