瀏覽代碼

Merge branch 'no_sharding'

# Conflicts:
#	cif-service/src/main/java/com/txz/cif/service/impl/FlowServiceImpl.java
#	cif-service/src/main/java/com/txz/cif/task/GeneralJob.java
Mr.qian 3 周之前
父節點
當前提交
fc3ac43b63

+ 8 - 0
cif-service/src/main/java/com/txz/cif/dao/AccountFreezdMapper.java

@@ -2,6 +2,14 @@ package com.txz.cif.dao;
 
 import com.txz.cif.core.Mapper;
 import com.txz.cif.model.AccountFreezd;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Select;
+
+import java.math.BigDecimal;
 
 public interface AccountFreezdMapper extends Mapper<AccountFreezd> {
+    
+    @Select("SELECT IFNULL(SUM(amount), 0) - IFNULL(SUM(unfreeze_amount), 0) FROM c_account_freezd WHERE type = 2 AND status IN (1,2) AND user_id = #{userId} ")
+    BigDecimal sumFreezdForRefundByUserId(@Param("userId") Long userId);
+    
 }

+ 0 - 3
cif-service/src/main/java/com/txz/cif/dubbo/impl/AccountDubboServiceImpl.java

@@ -6,8 +6,6 @@ import cn.hutool.core.date.DateUtil;
 import cn.hutool.core.util.StrUtil;
 import com.alibaba.fastjson.JSONObject;
 import com.txz.cif.configurer.LocalUtil;
-import com.txz.cif.core.ResultCode;
-import com.txz.cif.core.ResultGenerator;
 import com.txz.cif.core.ServiceException;
 import com.txz.cif.dto.AccountDTO;
 import com.txz.cif.dto.Result;
@@ -21,7 +19,6 @@ import com.txz.cif.web.para.RedEnvelopeParam;
 import com.txz.operating.dto.ConfigDTO;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.dubbo.config.annotation.DubboService;
-import org.apache.dubbo.config.annotation.Service;
 
 import javax.annotation.Resource;
 import java.math.BigDecimal;

+ 38 - 0
cif-service/src/main/java/com/txz/cif/enums/AccountFreezdTypeEnum.java

@@ -0,0 +1,38 @@
+package com.txz.cif.enums;
+
+import com.baomidou.mybatisplus.annotation.EnumValue;
+import com.fasterxml.jackson.annotation.JsonValue;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * @author: MTD®️
+ * @date: 2025/10/20
+ */
+@AllArgsConstructor
+public enum AccountFreezdTypeEnum {
+    
+    /**
+     * 提现冻结
+     */
+    WITHDRAWAL_FREEZE(1, "WITHDRAWAL_FREEZE"),
+    
+    /**
+     * 退款冻结
+     */
+    REFUND_FREEZE(2, "REFUND_FREEZE"),
+    
+    ;
+    
+    @Setter
+    @Getter
+    @EnumValue
+    private Integer code;
+    
+    @Setter
+    @Getter
+    @JsonValue
+    private String desc;
+    
+}

+ 19 - 2
cif-service/src/main/java/com/txz/cif/model/AccountFreezd.java

@@ -1,12 +1,13 @@
 package com.txz.cif.model;
 
+import com.txz.cif.enums.AccountFreezdTypeEnum;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.*;
 
+import javax.persistence.*;
 import java.math.BigDecimal;
 import java.util.Date;
-import javax.persistence.*;
 
 @Getter
 @Setter
@@ -21,6 +22,11 @@ public class AccountFreezd {
     @ApiModelProperty(value="id")
     private Long id;
 
+    /**
+     * 用户id
+     */
+    private Long userId;
+    
     /**
      * 账户id
      */
@@ -67,6 +73,17 @@ public class AccountFreezd {
     @Column(name = "update_time")
     @ApiModelProperty(value="updateTime更新时间")
     private Date updateTime;
-
+    
+    private String version;
+    
+    /**
+     * 类型 1提现冻结 2退款冻结
+     */
+    private AccountFreezdTypeEnum type;
+    
+    /**
+     * 解冻时间
+     */
+    private Date unfreezeTime;
 
 }

+ 4 - 0
cif-service/src/main/java/com/txz/cif/service/AccountFreezdService.java

@@ -2,10 +2,14 @@ package com.txz.cif.service;
 import com.txz.cif.model.AccountFreezd;
 import com.txz.cif.core.Service;
 
+import java.math.BigDecimal;
+
 
 /**
  * Created by CodeGenerator on 2022/11/19.
  */
 public interface AccountFreezdService extends Service<AccountFreezd> {
 
+    BigDecimal sumFreezdForRefundByUserId(Long userId);
+    
 }

+ 34 - 14
cif-service/src/main/java/com/txz/cif/service/FlowService.java

@@ -1,65 +1,85 @@
 package com.txz.cif.service;
+
 import com.txz.cif.dto.Result;
 import com.txz.cif.model.Flow;
 import com.txz.cif.core.Service;
 import com.txz.cif.model.RedEnvelope;
 import com.txz.cif.param.*;
-import tk.mybatis.mapper.entity.Condition;
+import com.txz.cif.web.para.FreezdParam;
 
+import java.math.BigDecimal;
 import java.util.HashMap;
 
 /**
  * Created by CodeGenerator on 2022/11/02.
  */
 public interface FlowService extends Service<Flow> {
-
-
+    
+    
     /**
      * 冻结
+     *
      * @param param
+     *
      * @return 流水号
      */
     Result freeze(FreezdParam param);
-
+    
     /**
      * 解冻(全额解冻)
+     *
      * @param freezdId
      */
     Result unFreeze(Long freezdId);
-
+    
     /**
      * 充值
+     *
      * @param param
+     *
      * @return
      */
     Result recharge(RechargeParam param);
-
+    
     /**
      * 支付
+     *
      * @param param
+     *
      * @return
      */
     Result pay(PayParam param);
-
+    
     /**
      * 退款
+     *
      * @param param
+     *
      * @return
      */
     Result refund(RefundParam param);
-
-
-
+    
+    
     /**
      * 提现
+     *
      * @param param
+     *
      * @return
      */
     Result withdraw(WithdrawParam param);
-
-
+    
+    
     Result settle(RedEnvelope redEnvelope);
-
-
+    
+    
     Integer countByUserId(HashMap map);
+    
+    /**
+     * 部分解冻
+     */
+    BigDecimal partialThaw(Long id, BigDecimal partialThawAmount);
+    
+    void unfreezeRefund();
+    
 }

+ 7 - 1
cif-service/src/main/java/com/txz/cif/service/impl/AccountFreezdServiceImpl.java

@@ -8,6 +8,7 @@ import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
 import javax.annotation.Resource;
+import java.math.BigDecimal;
 
 
 /**
@@ -16,7 +17,12 @@ import javax.annotation.Resource;
 @Service
 @Transactional
 public class AccountFreezdServiceImpl extends AbstractService<AccountFreezd> implements AccountFreezdService {
+    
     @Resource
     private AccountFreezdMapper cAccountFreezdMapper;
-
+    
+    @Override
+    public BigDecimal sumFreezdForRefundByUserId(Long userId) {
+        return cAccountFreezdMapper.sumFreezdForRefundByUserId(userId);
+    }
 }

+ 142 - 21
cif-service/src/main/java/com/txz/cif/service/impl/FlowServiceImpl.java

@@ -1,5 +1,7 @@
 package com.txz.cif.service.impl;
 
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.collection.CollectionUtil;
 import cn.hutool.core.date.DateUtil;
 import com.txz.cif.configurer.LocalUtil;
 import com.txz.cif.constants.MyConstants;
@@ -7,20 +9,31 @@ import com.txz.cif.core.AbstractService;
 import com.txz.cif.core.ServiceException;
 import com.txz.cif.dao.FlowMapper;
 import com.txz.cif.dto.Result;
+import com.txz.cif.dubbo.client.OperatingConfigDubboServiceClient;
+import com.txz.cif.enums.AccountFreezdTypeEnum;
 import com.txz.cif.enums.BizTypeEnum;
 import com.txz.cif.model.*;
+import com.txz.cif.param.PayParam;
+import com.txz.cif.param.RechargeParam;
+import com.txz.cif.param.RefundParam;
+import com.txz.cif.param.WithdrawParam;
+import com.txz.cif.service.AccountFlowService;
 import com.txz.cif.param.*;
 import com.txz.cif.service.AccountFreezdService;
 import com.txz.cif.service.AccountService;
 import com.txz.cif.service.FlowService;
+import com.txz.cif.web.para.FreezdParam;
+import com.txz.operating.dto.ConfigDTO;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
+import tk.mybatis.mapper.entity.Condition;
 
 import javax.annotation.Resource;
 import java.math.BigDecimal;
 import java.util.Date;
 import java.util.HashMap;
+import java.util.List;
 
 /**
  * Created by CodeGenerator on 2022/11/02.
@@ -31,13 +44,20 @@ import java.util.HashMap;
 public class FlowServiceImpl extends AbstractService<Flow> implements FlowService {
     @Resource
     private FlowMapper cFlowMapper;
-
+    
     @Resource
     private AccountService accountService;
     
+    
+    @Resource
+    private AccountFlowService accountFlowService;
+    
     @Resource
     private AccountFreezdService accountFreezdService;
-
+    
+    @Resource
+    private OperatingConfigDubboServiceClient operatingConfigDubboServiceClient;
+    
     @Override
     public Result freeze(FreezdParam param) {
         try{
@@ -60,9 +80,19 @@ public class FlowServiceImpl extends AbstractService<Flow> implements FlowServic
                     .bizId(flow.getBizId()).aliases(account.getAliases()).transTime(param.getTransTime()).userId(flow.getUserId())
                     .bizNo(flow.getBizNo()).balance(account.getBalance()).freezeAmount(account.getFreezeAmount().add(param.getAmount()))
                     .flowType(4).type(1).bizType(param.getBizType()).flowId(flow.getId()).build());
-            AccountFreezd freezd = AccountFreezd.builder().accountId(account.getId()).bizId(flow.getId())
-                    .amount(param.getAmount()).createTime(today).unfreezeAmount(BigDecimal.ZERO)
-                    .updateTime(today).status(1).build();
+            AccountFreezd freezd = AccountFreezd
+                    .builder()
+                    .userId(param.getUserId())
+                    .accountId(account.getId())
+                    .bizId(flow.getId())
+                    .amount(param.getAmount())
+                    .createTime(today)
+                    .unfreezeAmount(BigDecimal.ZERO)
+                    .type(param.getType())
+                    .updateTime(today)
+                    .status(1)
+                    .unfreezeTime(param.getUnfreezeTime())
+                    .build();
             accountFreezdService.saveUseGeneratedKeys(freezd);
             return Result.genSuccessResult(freezd.getId());
         }catch (Exception e){
@@ -168,12 +198,12 @@ public class FlowServiceImpl extends AbstractService<Flow> implements FlowServic
                 .bizNo(flow.getBizNo()).balance(account.getBalance().add(flow.getAmount()))
                 .freezeAmount(account.getFreezeAmount()).userId(flow.getUserId())
                 .flowType(1).type(2).bizType(param.getBizType()).flowId(flow.getId()).build());
-
-
-        if (param.getDiscount().compareTo(BigDecimal.ZERO) > 0){
-            //充值返点
+        
+        
+        if (param.getDiscount().compareTo(BigDecimal.ZERO) > 0) {
+            // 充值返点
             Account innerRebateAccount = accountService.findById(MyConstants.INNER_REBATE);
-            if (innerCapitalAccount == null){
+            if (innerCapitalAccount == null) {
                 return Result.genFailResult(LocalUtil.get("account.not.found"));
             }
             flow = Flow.builder().amount(param.getDiscount()).bizType(BizTypeEnum.REFUND_RECHARGE.getKey())
@@ -212,14 +242,45 @@ public class FlowServiceImpl extends AbstractService<Flow> implements FlowServic
         if (innerIncomeAccount == null){
             return Result.genFailResult(LocalUtil.get("account.not.found"));
         }
-
-        //借:个人账户钱包(贷)     -500元
-        //贷:平台主营收入(贷)   +500元
+        
+        // 冻结金额
+        BigDecimal sumFreezdAmount = accountFreezdService.sumFreezdForRefundByUserId(param.getUserId());
+        
+        if (sumFreezdAmount.compareTo(BigDecimal.ZERO) == 0) {
+            if (account.getBalance().subtract(account.getFreezeAmount()).add(sumFreezdAmount).compareTo(param.getAmount()) == -1) {
+                return Result.genFailResult(LocalUtil.get("account.not.found"));
+            }
+            Condition c = new Condition(AccountFreezd.class);
+            c.createCriteria()
+                    .andEqualTo("type", AccountFreezdTypeEnum.REFUND_FREEZE)
+                    .andIn("status", CollUtil.newArrayList(1, 2))
+                    .andEqualTo("userId", param.getUserId())
+            ;
+            c.setOrderByClause("create_time");
+            List<AccountFreezd> accounts = accountFreezdService.findByCondition(c);
+            if (CollectionUtil.isNotEmpty(accounts)) {
+                BigDecimal totalAmount = param.getAmount();
+                for (AccountFreezd accountFreezd : accounts) {
+                    totalAmount = partialThaw(accountFreezd.getId(), totalAmount);
+                    if (totalAmount.compareTo(BigDecimal.ZERO) == 0) {
+                        break;
+                    }
+                }
+            }
+        }
+        
+        // 借:个人账户钱包(贷)     -500元
+        // 贷:平台主营收入(贷)   +500元
         Date today = DateUtil.date();
         Flow flow = Flow.builder().amount(param.getAmount()).bizType(param.getBizType())
                 .userId(param.getUserId())
-                .bizNo(param.getBizNo()).createTime(today).updateTime(today).transTime(param.getTransTime())
-                .debitAccount(account.getId()).creditAccount(MyConstants.INNER_INCOME).createUser(param.getUserId()+"")
+                .bizNo(param.getBizNo())
+                .createTime(today)
+                .updateTime(today)
+                .transTime(param.getTransTime())
+                .debitAccount(account.getId())
+                .creditAccount(MyConstants.INNER_INCOME)
+                .createUser(param.getUserId() + "")
                 .bizId(param.getBizId()).type(6)
                 .build();
         saveUseGeneratedKeys(flow);
@@ -259,6 +320,24 @@ public class FlowServiceImpl extends AbstractService<Flow> implements FlowServic
                 .debitAccount(MyConstants.INNER_REFUND).creditAccount(account.getId())
                 .bizId(param.getBizId()).type(9).createUser(param.getUserId()+"")
                 .build();
+        
+        com.txz.operating.result.Result<ConfigDTO> refundFreezeTime = operatingConfigDubboServiceClient.getConfigByCode("refund_freeze_time");
+        int days = Integer.parseInt(refundFreezeTime.getData().getValueInfo());
+        Date unfreezeTime = DateUtil.offsetDay(new Date(), days);
+        
+        freeze(FreezdParam.builder()
+                .userId(param.getUserId())
+                .accountType(account.getType())
+                .amount(param.getAmount())
+                .bizType(param.getBizType())
+                .bizId(param.getBizId())
+                .bizNo(param.getBizNo())
+                .transTime(param.getTransTime())
+                .userId(param.getUserId())
+                .type(AccountFreezdTypeEnum.REFUND_FREEZE)
+                .unfreezeTime(unfreezeTime)
+                .build()
+        );
         saveUseGeneratedKeys(flow);
         //借:主营支出-退款(借)     +100元
         accountService.deal(AccountFlow.builder().accountId(MyConstants.INNER_REFUND).amount(flow.getAmount())
@@ -288,11 +367,18 @@ public class FlowServiceImpl extends AbstractService<Flow> implements FlowServic
         }
 
         Date today = DateUtil.date();
-        Flow flow = Flow.builder().amount(param.getAmount()).bizType(param.getBizType())
+        Flow flow = Flow.builder()
+                .amount(param.getAmount())
+                .bizType(param.getBizType())
                 .userId(param.getUserId())
-                .bizNo(param.getBizNo()).createTime(today).updateTime(today).transTime(param.getTransTime())
-                .creditAccount(MyConstants.INNER_CAPITAL).debitAccount(account.getId())
-                .bizId(param.getBizId()).type(3)
+                .bizNo(param.getBizNo())
+                .createTime(today)
+                .updateTime(today)
+                .transTime(param.getTransTime())
+                .creditAccount(MyConstants.INNER_CAPITAL)
+                .debitAccount(account.getId())
+                .bizId(param.getBizId())
+                .type(3)
                 .build();
         saveUseGeneratedKeys(flow);
 
@@ -347,6 +433,41 @@ public class FlowServiceImpl extends AbstractService<Flow> implements FlowServic
     public Integer countByUserId(HashMap map) {
         return cFlowMapper.countByUserId(map);
     }
-
-
+    
+    @Override
+    public BigDecimal partialThaw(Long id, BigDecimal partialThawAmount) {
+        AccountFreezd accountFreezd = accountFreezdService.findById(id);
+        // 可用冻结金额
+        BigDecimal canUseAmount = accountFreezd.getAmount().subtract(accountFreezd.getUnfreezeAmount());
+        // 可用金额小于等于总金额
+        if (canUseAmount.compareTo(partialThawAmount) != 1) {
+            accountFreezd.setStatus(3);
+            accountFreezd.setUnfreezeAmount(accountFreezd.getAmount());
+            accountFreezd.setUpdateTime(new Date());
+            accountFreezdService.update(accountFreezd);
+            return partialThawAmount.subtract(canUseAmount);
+        } else {
+            accountFreezd.setStatus(2);
+            accountFreezd.setUnfreezeAmount(accountFreezd.getUnfreezeAmount().add(partialThawAmount));
+            accountFreezd.setUpdateTime(new Date());
+            accountFreezdService.update(accountFreezd);
+            return BigDecimal.ZERO;
+        }
+    }
+    
+    @Override
+    public void unfreezeRefund() {
+        Condition c = new Condition(AccountFreezd.class);
+        c.createCriteria()
+                .andEqualTo("type", AccountFreezdTypeEnum.REFUND_FREEZE)
+                .andIn("status", CollUtil.newArrayList(1, 2))
+                .andLessThanOrEqualTo("unfreezeTime", new Date())
+        ;
+        List<AccountFreezd> accounts = accountFreezdService.findByCondition(c);
+        for (AccountFreezd accountFreezd : accounts) {
+            unFreeze(accountFreezd.getId());
+        }
+    }
+    
+    
 }

+ 16 - 11
cif-service/src/main/java/com/txz/cif/service/impl/WithdrawRecordServiceImpl.java

@@ -12,14 +12,14 @@ import com.txz.cif.configurer.LocalUtil;
 import com.txz.cif.constants.MyConstants;
 import com.txz.cif.core.AbstractService;
 import com.txz.cif.core.ServiceException;
-import com.txz.cif.dao.UserMapper;
 import com.txz.cif.dao.WithdrawRecordMapper;
 import com.txz.cif.dto.BizLogDTO;
 import com.txz.cif.dto.Result;
 import com.txz.cif.dto.tfpay.TFWithdrawDTO;
+import com.txz.cif.enums.AccountFreezdTypeEnum;
 import com.txz.cif.enums.BizTypeEnum;
 import com.txz.cif.model.*;
-import com.txz.cif.param.FreezdParam;
+import com.txz.cif.web.para.FreezdParam;
 import com.txz.cif.param.WithdrawParam;
 import com.txz.cif.service.*;
 import com.txz.cif.util.TFPayUtil;
@@ -41,7 +41,7 @@ import java.util.Map;
 @Slf4j
 @Transactional
 public class WithdrawRecordServiceImpl extends AbstractService<WithdrawRecord> implements WithdrawRecordService {
-
+    
     @Resource
     private WithdrawRecordMapper withdrawRecordMapper;
     @Resource
@@ -71,13 +71,17 @@ public class WithdrawRecordServiceImpl extends AbstractService<WithdrawRecord> i
     @Override
     public void add(WithdrawRecord withdrawRecord) {
         saveUseGeneratedKeys(withdrawRecord);
-        Account account = accountService.getAccount(withdrawRecord.getUserId(), withdrawRecord.getAccountType());
+        // Account account = accountService.getAccount(withdrawRecord.getUserId(), withdrawRecord.getAccountType());
         // 冻结金额+手续费
-        Result freeze = flowService.freeze(FreezdParam.builder().accountType(withdrawRecord.getAccountType())
+        Result freeze = flowService.freeze(FreezdParam.builder()
+                .userId(withdrawRecord.getUserId())
+                .accountType(withdrawRecord.getAccountType())
                 .amount(withdrawRecord.getAmount().add(withdrawRecord.getFee())).bizType(BizTypeEnum.WITHDRAW.getKey())
-                .bizId(withdrawRecord.getId() + "").bizNo(withdrawRecord.getOrderNo())
+                .bizId(withdrawRecord.getId() + "")
+                .bizNo(withdrawRecord.getOrderNo())
                 .transTime(withdrawRecord.getTransTime())
                 .userId(withdrawRecord.getUserId())
+                .type(AccountFreezdTypeEnum.WITHDRAWAL_FREEZE)
                 .build());
         update(WithdrawRecord.builder().id(withdrawRecord.getId()).freezeId(Long.valueOf(freeze.getData().toString())).build());
     }
@@ -168,7 +172,8 @@ public class WithdrawRecordServiceImpl extends AbstractService<WithdrawRecord> i
             flowService.unFreeze(record.getFreezeId());
         }
         flowService.withdraw(WithdrawParam.builder()
-                .accountType(record.getAccountType()).bizType(BizTypeEnum.WITHDRAW.getKey())
+                .accountType(record.getAccountType())
+                .bizType(BizTypeEnum.WITHDRAW.getKey())
                 .userId(record.getUserId())
                 .amount(record.getAmount())
                 .bizId(record.getId() + "")
@@ -185,14 +190,14 @@ public class WithdrawRecordServiceImpl extends AbstractService<WithdrawRecord> i
         }
         update(WithdrawRecord.builder().id(record.getId()).status(5).build());
     }
-
+    
     @Override
     public Integer countByUserId(HashMap map) {
-        return withdrawRecordMapper.countByUserId( map);
+        return withdrawRecordMapper.countByUserId(map);
     }
-
+    
     @Override
     public BigDecimal sumByStatus(HashMap map) {
-        return withdrawRecordMapper.sumByStatus( map);
+        return withdrawRecordMapper.sumByStatus(map);
     }
 }

+ 26 - 14
cif-service/src/main/java/com/txz/cif/task/GeneralJob.java

@@ -5,7 +5,6 @@ import cn.hutool.core.date.DateUtil;
 import cn.hutool.http.HttpRequest;
 import cn.hutool.http.HttpResponse;
 import com.txz.cif.configurer.Parameters;
-import com.txz.cif.dao.ShardingMapper;
 import com.txz.cif.dubbo.client.OrderDubboServiceClient;
 import com.txz.cif.model.RedEnvelope;
 import com.txz.cif.service.DayCutService;
@@ -49,13 +48,16 @@ public class GeneralJob {
     
     @Resource
     private RechargeRecordService rechargeRecordService;
-    
+
     @Resource
     private RedEnvelopeService redEnvelopeService;
     
     @Resource
     private ShardingMapper shardingMapper;
     
+    @Resource
+    private FlowService flowService;
+    
     /**
      * 日切
      */
@@ -71,14 +73,11 @@ public class GeneralJob {
         }
         return ReturnT.SUCCESS;
     }
-    
+
     /**
      * 结算
-     *
      * @param param
-     *
      * @return
-     *
      * @throws Exception
      */
     @XxlJob("settle")
@@ -86,13 +85,13 @@ public class GeneralJob {
         try {
             logger.info("【执行结算】开始");
             Condition c = new Condition(RedEnvelope.class);
-            c.createCriteria().andEqualTo("status", 1).andLessThanOrEqualTo("settleTime", DateUtil.now());
+            c.createCriteria().andEqualTo("status",1).andLessThanOrEqualTo("settleTime", DateUtil.now());
             List<RedEnvelope> redEnvelopes = redEnvelopeService.findByCondition(c);
-            if (CollUtil.isNotEmpty(redEnvelopes)) {
-                for (RedEnvelope r : redEnvelopes) {
+            if (CollUtil.isNotEmpty(redEnvelopes)){
+                for (RedEnvelope r: redEnvelopes){
                     try {
                         redEnvelopeService.settle(r);
-                    } catch (Exception e) {
+                    }catch (Exception e) {
                         logger.error("【执行结算】异常:e{}", e);
                         return ReturnT.FAIL;
                     }
@@ -119,6 +118,7 @@ public class GeneralJob {
         logger.error("[checkin]:" + ret);
         
         
+
         return ReturnT.SUCCESS;
     }
     
@@ -162,7 +162,7 @@ public class GeneralJob {
         }
         return ReturnT.SUCCESS;
     }
-    
+
     @XxlJob("activityStatusJudgmentTimedTask")
     public ReturnT<String> activityStatusJudgmentTimedTask(String param) throws Exception {
         try {
@@ -175,8 +175,8 @@ public class GeneralJob {
         }
         return ReturnT.SUCCESS;
     }
-    
-    
+
+
     @XxlJob("closeRecharge")
     public ReturnT<String> closeRecharge() throws Exception {
         try {
@@ -190,6 +190,18 @@ public class GeneralJob {
         return ReturnT.SUCCESS;
     }
     
+    @XxlJob("unfreezeRefund")
+    public ReturnT<String> unfreezeRefund() throws Exception {
+        try {
+            logger.info("【退款解冻】开始");
+            flowService.unfreezeRefund();
+            logger.info("【退款解冻】完成");
+        } catch (Exception e) {
+            logger.error("【退款解冻】异常:e{}", e);
+            return ReturnT.FAIL;
+        }
+        return ReturnT.SUCCESS;
+    }
     
     public static void main(String[] args) {
         //        int quhao = 154;
@@ -219,4 +231,4 @@ public class GeneralJob {
     }
     
     
-}
+}

+ 186 - 144
cif-service/src/main/java/com/txz/cif/web/AccountApiController.java

@@ -1,172 +1,214 @@
 package com.txz.cif.web;
+
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.collection.CollectionUtil;
 import cn.hutool.core.date.DateUtil;
-import cn.hutool.core.util.StrUtil;
+import com.github.pagehelper.PageHelper;
+import com.github.pagehelper.PageInfo;
 import com.txz.cif.core.*;
 import com.txz.cif.model.Account;
 import com.txz.cif.model.AccountFlow;
+import com.txz.cif.model.AccountFreezd;
 import com.txz.cif.model.User;
-import com.txz.cif.service.AccountFlowService;
-import com.txz.cif.service.AccountService;
-import com.txz.cif.service.RedEnvelopeService;
-import com.txz.cif.service.UserService;
-import com.txz.cif.web.bo.*;
+import com.txz.cif.service.*;
+import com.txz.cif.web.bo.AccountFlowBO;
+import com.txz.cif.web.bo.AccountInfoBO;
+import com.txz.cif.web.bo.AccountWalletInfoBO;
 import com.txz.cif.web.para.AccountFlowParam;
-
-import com.github.pagehelper.PageHelper;
-import com.github.pagehelper.PageInfo;
-import org.springframework.web.bind.annotation.*;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import com.txz.cif.web.vo.AccountFreezdVO;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
-
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.web.bind.annotation.*;
 import tk.mybatis.mapper.entity.Condition;
 import tk.mybatis.mapper.entity.Example.Criteria;
 
 import javax.annotation.Resource;
 import javax.servlet.http.HttpServletRequest;
 import java.math.BigDecimal;
+import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
 import java.util.stream.Collectors;
 
 
 /**
-* Created by CodeGenerator on 2022/11/16.
-*/
+ * Created by CodeGenerator on 2022/11/16.
+ */
 @Api(tags = "[api]结算管理")
 @RestController
 @RequestMapping("/account/api")
 public class AccountApiController extends AbstractApiController {
-
-	private static Logger log = LoggerFactory.getLogger(AccountApiController.class);
-
+    
+    private static Logger log = LoggerFactory.getLogger(AccountApiController.class);
+    
     @Resource
     private AccountFlowService accountFlowService;
-
-	@Resource
-	private AccountService accountService;
-
-	@Resource
-	private RedEnvelopeService redEnvelopeService;
-
-
-	@Resource
-	private UserService userService;
-	@Resource
-	private AuthService authService;
-
-	@ApiOperation(value = "查询收益账号信息", notes = "",httpMethod = "GET")
-	@GetMapping("/getAccountInfo")
-	public Result<AccountInfoBO> getAccountInfo(HttpServletRequest request) {
-		Long userId = authService.getTokenUserId(request);
-		if (userId == null ){
-			return ResultGenerator.genFailResult(ResultCode.OAUTH_INVALID_ACCESS_TOKEN);
-		}
-		User user = userService.findById(userId);
-		if (user == null ){
-			return ResultGenerator.genFailResult(ResultCode.USER_IS_NULL);
-
-		}
-		Account earnings = accountService.getAccount(userId, 2);
-		AccountInfoBO bo = new AccountInfoBO();
-		bo.setBalance(earnings.getBalance());
-		bo.setSettledAmount(earnings.getTotalInamount());
-		BigDecimal pendingAmount = redEnvelopeService.sumWithDay(null,userId,1);
-		if (pendingAmount == null){
-			pendingAmount = BigDecimal.ZERO;
-		}
-		bo.setPendingAmount(pendingAmount);
-
-		BigDecimal tDEamings = redEnvelopeService.sumWithDay(DateUtil.today(),userId,null);
-		if (tDEamings == null){
-			tDEamings = BigDecimal.ZERO;
-		}
-		bo.setTDEamings(tDEamings);
-		BigDecimal yDEamings = redEnvelopeService.sumWithDay(DateUtil.yesterday().toDateStr(),userId,null);
-		if (yDEamings == null){
-			yDEamings = BigDecimal.ZERO;
-		}
-		bo.setYDEamings(yDEamings.subtract(tDEamings));
-		BigDecimal mTDEamings = redEnvelopeService.sumWithDay(DateUtil.beginOfMonth(DateUtil.date()).toDateStr(),userId,null);
-		if (mTDEamings == null){
-			mTDEamings = BigDecimal.ZERO;
-		}
-		bo.setMTDEamings(mTDEamings);
-		BigDecimal settleAmount = redEnvelopeService.sumWithDay(null,userId,2);
-		if (settleAmount == null){
-			settleAmount = BigDecimal.ZERO;
-		}
-		bo.setSettledAmount(settleAmount);
-		BigDecimal totalEarnings = settleAmount.add(pendingAmount);
-		bo.setTotalEarnings(totalEarnings);
-		return ResultGenerator.genSuccessResult(bo);
-	}
-
-	@ApiOperation(value = "查询钱包账号信息", notes = "",httpMethod = "GET")
-	@GetMapping("/getWalletAccountInfo")
-	public Result<AccountWalletInfoBO> getWalletAccountInfo(HttpServletRequest request) {
-		Long userId = authService.getTokenUserId(request);
-		if (userId == null ){
-			return ResultGenerator.genFailResult(ResultCode.OAUTH_INVALID_ACCESS_TOKEN);
-		}
-		User user = userService.findById(userId);
-		if (user == null ){
-			return ResultGenerator.genFailResult(ResultCode.USER_IS_NULL);
-		}
-		Account wallet = accountService.getAccount(userId, 1);
-		AccountWalletInfoBO bo = new AccountWalletInfoBO();
-		bo.setBalance(wallet.getBalance());
-		bo.setFreezeAmount(wallet.getFreezeAmount());
-		return ResultGenerator.genSuccessResult(bo);
-	}
-
-
-	@PostMapping("/accountFlowList")
-	@ApiOperation(value = "出入流水",httpMethod = "POST")
-	public Result<AccountFlowBO> accountFlowList(@RequestBody AccountFlowParam param,HttpServletRequest request) {
-		Long userId = authService.getTokenUserId(request);
-		if (userId == null ){
-			return ResultGenerator.genFailResult(ResultCode.OAUTH_INVALID_ACCESS_TOKEN);
-		}
-		User user = userService.findById(userId);
-		if (user == null){
-			return ResultGenerator.genFailResult(ResultCode.USER_IS_NULL);
-		}
-		Account account = accountService.getAccount(userId, 1);
-		if (account == null){
-			return ResultGenerator.genFailResult(ResultCode.ACCOUNT_IS_NULL);
-		}
-		PageHelper.startPage(param.getPage(), param.getSize());
-		Condition c = new Condition(AccountFlow.class);
-		Criteria criteria = c.createCriteria().andEqualTo("accountId",account.getId());
-		if (param.getType() == 1 ){
-			criteria.andGreaterThanOrEqualTo("createTime", DateUtil.today());
-		} else if (param.getType() == 2){
-			Date yesterdayStart = DateUtil.beginOfDay(DateUtil.yesterday());
-			Date todayStart = DateUtil.beginOfDay(DateUtil.date());
-			criteria.andBetween("createTime", yesterdayStart,todayStart);
-		} else if (param.getType() == 3){
-			Date start = DateUtil.beginOfDay(DateUtil.offsetDay(DateUtil.date(),-7));
-			criteria.andGreaterThanOrEqualTo("createTime",start);
-		} else if (param.getType() == 4){
-			Date start = DateUtil.beginOfMonth(DateUtil.date());
-			criteria.andGreaterThanOrEqualTo("createTime",start);
-		} else if (param.getType() == 5){
-			Date start = DateUtil.beginOfYear(DateUtil.date());
-			criteria.andGreaterThanOrEqualTo("createTime",start);
-		}
-		c.setOrderByClause("create_time desc");
-		List<AccountFlow> flows = accountFlowService.findByCondition(c);
-		PageInfo pageInfo = new PageInfo(flows);
-		List<AccountFlowBO> bos = flows.stream().map(temp -> {
-			AccountFlowBO bo = temp.generator();
-			if (account != null){
-				bo.setAccountName(account.getName());
-			}
-			return bo;
-		}).collect(Collectors.toList());
-		pageInfo.setList(bos);
-		return ResultGenerator.genSuccessResult(pageInfo);
-	}
+    
+    @Resource
+    private AccountService accountService;
+    
+    @Resource
+    private RedEnvelopeService redEnvelopeService;
+    
+    
+    @Resource
+    private UserService userService;
+    @Resource
+    private AuthService authService;
+    
+    @Resource
+    private AccountFreezdService accountFreezdService;
+    
+    @ApiOperation(value = "查询收益账号信息", notes = "", httpMethod = "GET")
+    @GetMapping("/getAccountInfo")
+    public Result<AccountInfoBO> getAccountInfo(HttpServletRequest request) {
+        Long userId = authService.getTokenUserId(request);
+        if (userId == null) {
+            return ResultGenerator.genFailResult(ResultCode.OAUTH_INVALID_ACCESS_TOKEN);
+        }
+        User user = userService.findById(userId);
+        if (user == null) {
+            return ResultGenerator.genFailResult(ResultCode.USER_IS_NULL);
+            
+        }
+        Account earnings = accountService.getAccount(userId, 2);
+        AccountInfoBO bo = new AccountInfoBO();
+        bo.setBalance(earnings.getBalance());
+        bo.setSettledAmount(earnings.getTotalInamount());
+        BigDecimal pendingAmount = redEnvelopeService.sumWithDay(null, userId, 1);
+        if (pendingAmount == null) {
+            pendingAmount = BigDecimal.ZERO;
+        }
+        bo.setPendingAmount(pendingAmount);
+        
+        BigDecimal tDEamings = redEnvelopeService.sumWithDay(DateUtil.today(), userId, null);
+        if (tDEamings == null) {
+            tDEamings = BigDecimal.ZERO;
+        }
+        bo.setTDEamings(tDEamings);
+        BigDecimal yDEamings = redEnvelopeService.sumWithDay(DateUtil.yesterday().toDateStr(), userId, null);
+        if (yDEamings == null) {
+            yDEamings = BigDecimal.ZERO;
+        }
+        bo.setYDEamings(yDEamings.subtract(tDEamings));
+        BigDecimal mTDEamings = redEnvelopeService.sumWithDay(DateUtil.beginOfMonth(DateUtil.date()).toDateStr(), userId, null);
+        if (mTDEamings == null) {
+            mTDEamings = BigDecimal.ZERO;
+        }
+        bo.setMTDEamings(mTDEamings);
+        BigDecimal settleAmount = redEnvelopeService.sumWithDay(null, userId, 2);
+        if (settleAmount == null) {
+            settleAmount = BigDecimal.ZERO;
+        }
+        bo.setSettledAmount(settleAmount);
+        BigDecimal totalEarnings = settleAmount.add(pendingAmount);
+        bo.setTotalEarnings(totalEarnings);
+        return ResultGenerator.genSuccessResult(bo);
+    }
+    
+    @ApiOperation(value = "查询钱包账号信息", notes = "", httpMethod = "GET")
+    @GetMapping("/getWalletAccountInfo")
+    public Result<AccountWalletInfoBO> getWalletAccountInfo(HttpServletRequest request) {
+        Long userId = authService.getTokenUserId(request);
+        if (userId == null) {
+            return ResultGenerator.genFailResult(ResultCode.OAUTH_INVALID_ACCESS_TOKEN);
+        }
+        User user = userService.findById(userId);
+        if (user == null) {
+            return ResultGenerator.genFailResult(ResultCode.USER_IS_NULL);
+        }
+        Account wallet = accountService.getAccount(userId, 1);
+        AccountWalletInfoBO bo = new AccountWalletInfoBO();
+        bo.setBalance(wallet.getBalance());
+        bo.setFreezeAmount(wallet.getFreezeAmount());
+        bo.setAvailableAmount(wallet.getBalance().subtract(wallet.getFreezeAmount()));
+        return ResultGenerator.genSuccessResult(bo);
+    }
+    
+    /**
+     * 冻结列表
+     */
+    @GetMapping("getFreeds")
+    public Result<PageInfo<List<AccountFreezdVO>>> getFreeds(AccountFlowParam param, HttpServletRequest request) {
+        Long userId = authService.getTokenUserId(request);
+        if (userId == null) {
+            return ResultGenerator.genFailResult(ResultCode.OAUTH_INVALID_ACCESS_TOKEN);
+        }
+        PageHelper.startPage(param.getPage(), param.getSize());
+        
+        Condition c = new Condition(AccountFreezd.class);
+        c.createCriteria()
+                .andIn("status", CollUtil.newArrayList(1, 2))
+                .andEqualTo("userId", userId)
+        ;
+        c.setOrderByClause("create_time desc");
+        List<AccountFreezd> accountFreezds = accountFreezdService.findByCondition(c);
+        if (CollectionUtil.isEmpty(accountFreezds)) {
+            return ResultGenerator.genSuccessResult(new PageInfo());
+        }
+        PageInfo pageInfo = new PageInfo(accountFreezds);
+        
+        List<AccountFreezd> list = pageInfo.getList();
+        
+        List<AccountFreezdVO> result = new ArrayList<>();
+        for (AccountFreezd accountFreezd : list) {
+            AccountFreezdVO freezdVO = BeanUtil.copyProperties(accountFreezd, AccountFreezdVO.class);
+            freezdVO.setFreezeAmount(freezdVO.getAmount().subtract(freezdVO.getUnfreezeAmount()));
+            result.add(freezdVO);
+        }
+        pageInfo.setList(result);
+        return ResultGenerator.genSuccessResult(pageInfo);
+    }
+    
+    
+    @PostMapping("/accountFlowList")
+    @ApiOperation(value = "出入流水", httpMethod = "POST")
+    public Result<AccountFlowBO> accountFlowList(@RequestBody AccountFlowParam param, HttpServletRequest request) {
+        Long userId = authService.getTokenUserId(request);
+        if (userId == null) {
+            return ResultGenerator.genFailResult(ResultCode.OAUTH_INVALID_ACCESS_TOKEN);
+        }
+        User user = userService.findById(userId);
+        if (user == null) {
+            return ResultGenerator.genFailResult(ResultCode.USER_IS_NULL);
+        }
+        Account account = accountService.getAccount(userId, 1);
+        if (account == null) {
+            return ResultGenerator.genFailResult(ResultCode.ACCOUNT_IS_NULL);
+        }
+        PageHelper.startPage(param.getPage(), param.getSize());
+        Condition c = new Condition(AccountFlow.class);
+        Criteria criteria = c.createCriteria().andEqualTo("accountId", account.getId());
+        if (param.getType() == 1) {
+            criteria.andGreaterThanOrEqualTo("createTime", DateUtil.today());
+        } else if (param.getType() == 2) {
+            Date yesterdayStart = DateUtil.beginOfDay(DateUtil.yesterday());
+            Date todayStart = DateUtil.beginOfDay(DateUtil.date());
+            criteria.andBetween("createTime", yesterdayStart, todayStart);
+        } else if (param.getType() == 3) {
+            Date start = DateUtil.beginOfDay(DateUtil.offsetDay(DateUtil.date(), -7));
+            criteria.andGreaterThanOrEqualTo("createTime", start);
+        } else if (param.getType() == 4) {
+            Date start = DateUtil.beginOfMonth(DateUtil.date());
+            criteria.andGreaterThanOrEqualTo("createTime", start);
+        } else if (param.getType() == 5) {
+            Date start = DateUtil.beginOfYear(DateUtil.date());
+            criteria.andGreaterThanOrEqualTo("createTime", start);
+        }
+        c.setOrderByClause("create_time desc");
+        List<AccountFlow> flows = accountFlowService.findByCondition(c);
+        PageInfo pageInfo = new PageInfo(flows);
+        List<AccountFlowBO> bos = flows.stream().map(temp -> {
+            AccountFlowBO bo = temp.generator();
+            if (account != null) {
+                bo.setAccountName(account.getName());
+            }
+            return bo;
+        }).collect(Collectors.toList());
+        pageInfo.setList(bos);
+        return ResultGenerator.genSuccessResult(pageInfo);
+    }
 }

+ 5 - 2
cif-service/src/main/java/com/txz/cif/web/bo/AccountWalletInfoBO.java

@@ -5,8 +5,6 @@ import io.swagger.annotations.ApiModelProperty;
 import lombok.*;
 
 import java.math.BigDecimal;
-import java.util.Date;
-import javax.persistence.*;
 @Getter
 @Setter
 @NoArgsConstructor
@@ -27,6 +25,11 @@ public class AccountWalletInfoBO {
      */
     @ApiModelProperty(value="冻结金额")
     private BigDecimal  freezeAmount;
+    
+    /**
+     * 可用金额
+     */
+    private BigDecimal availableAmount;
 
 
 }

+ 28 - 21
cif-api/src/main/java/com/txz/cif/param/FreezdParam.java → cif-service/src/main/java/com/txz/cif/web/para/FreezdParam.java

@@ -1,11 +1,12 @@
 /*
-*
-* FreezdParam.java
-* Copyright(C) 2017-2020 fendo公司
-* @date 2022-11-02
-*/
-package com.txz.cif.param;
-
+ *
+ * FreezdParam.java
+ * Copyright(C) 2017-2020 fendo公司
+ * @date 2022-11-02
+ */
+package com.txz.cif.web.para;
+
+import com.txz.cif.enums.AccountFreezdTypeEnum;
 import lombok.AllArgsConstructor;
 import lombok.Builder;
 import lombok.Data;
@@ -20,50 +21,56 @@ import java.util.Date;
 @AllArgsConstructor
 @NoArgsConstructor
 public class FreezdParam implements Serializable {
-
-
+    
+    
     /**
      * 业务编号
      */
     private String bizNo;
-
+    
     /**
      * 业务Id
      */
     private String bizId;
-
+    
     /**
      * 冻结账户
      */
     private Long userId;
-
+    
     /**
      * 冻结金额
      */
     private BigDecimal amount;
-
+    
     /**
      * 类型 1001充值 2001提现  3001开团支付 3002参团支付  4001未成团退款 4002成团退款 5001开团红包收益 5002参团红包收益 5003签到红包收益 5004下级红包佣金 5005下下级红包佣金 6001充值返点 7001提现手续费 8001冻结 9001解冻
      */
     private Integer bizType;
-
+    
     /**
      * 账户类型 1钱包账户 2收益账户
      */
     private Integer accountType;
-
-
+    
+    
     /**
      * 交易时间
      */
     private Date transTime;
-
+    
+    
+    /**
+     * 类型 1提现冻结 2退款冻结
+     */
+    private AccountFreezdTypeEnum type;
+    
+    private Date unfreezeTime;
+    
     /**
      * c_flow
      */
     private static final long serialVersionUID = 1L;
-
-
-
-
+    
+    
 }

+ 68 - 0
cif-service/src/main/java/com/txz/cif/web/vo/AccountFreezdVO.java

@@ -0,0 +1,68 @@
+package com.txz.cif.web.vo;
+
+import com.txz.cif.enums.AccountFreezdTypeEnum;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * @author: MTD®️
+ * @date: 2025/10/21
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class AccountFreezdVO {
+    
+     private Long id;
+
+    /**
+     * 用户id
+     */
+    private Long userId;
+    
+    /**
+     * 账户id
+     */
+    private Long accountId;
+
+    /**
+     * 流水号
+     */
+    private Long bizId;
+
+    /**
+     * 冻结金额
+     */
+    private BigDecimal amount;
+
+    /**
+     * 解冻金额
+     */
+    private BigDecimal unfreezeAmount;
+
+    /**
+     * 状态 1冻结中 2部分冻结 3已解冻
+     */
+    private Integer status;
+
+    /**
+     * 创建时间
+     */
+    private Date createTime;
+    
+    /**
+     * 类型 1提现冻结 2退款冻结
+     */
+    private AccountFreezdTypeEnum type;
+    
+    /**
+     * 解冻时间
+     */
+    private Date unfreezeTime;
+    
+    private BigDecimal freezeAmount;
+}