Преглед на файлове

feat: 领红包添加公司余额

xdd преди 4 дни
родител
ревизия
69c0b5ef14

+ 29 - 0
fs-admin/src/main/java/com/fs/qw/FsCourseTask.java

@@ -1,11 +1,19 @@
 package com.fs.qw;
 
+import com.fs.common.core.redis.RedisCache;
 import com.fs.course.service.IFsCourseWatchLogService;
 import com.fs.qw.service.IQwWorkTaskService;
+import com.fs.system.domain.SysConfig;
+import com.fs.system.mapper.SysConfigMapper;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections4.CollectionUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.List;
+
 /**
  * 后台统计相关 定时任务
  */
@@ -16,7 +24,28 @@ public class FsCourseTask {
     private IFsCourseWatchLogService fsCourseWatchLogService;
     @Autowired
     private IQwWorkTaskService qwWorkTaskService;
+    @Autowired
+    private RedisCache redisCache;
+    private static final String REDPACKET_COMPANY_MONEY_CHANGE = "redpacket_money_CHANGE";
+    @Autowired
+    private SysConfigMapper sysConfigMapper;
+    /**
+     * 公司红包金额变更
+     */
+    public void redpacketCompanyMoneyChange(){
+        List<BigDecimal> moneyChange = redisCache.getCacheList(REDPACKET_COMPANY_MONEY_CHANGE);
+        log.info("公司账户红包余额变更 {} -> {}",moneyChange.get(0).toPlainString(),moneyChange.get(1).toPlainString());
+
+        if(CollectionUtils.isNotEmpty(moneyChange)){
+            SysConfig sysConfig = new SysConfig();
+            BigDecimal bigDecimal = moneyChange.get(1);
+            sysConfig.setConfigValue(bigDecimal.setScale(4, RoundingMode.HALF_UP).toPlainString());
+            sysConfig.setConfigKey("company.money");
+            sysConfigMapper.updateConfig(sysConfig);
 
+            redisCache.deleteObject(REDPACKET_COMPANY_MONEY_CHANGE);
+        }
+    }
     /**
      * 添加企微观看日志
      * @throws Exception

+ 9 - 0
fs-service/src/main/java/com/fs/course/domain/FsCourseRedPacketLog.java

@@ -64,4 +64,13 @@ public class FsCourseRedPacketLog extends BaseEntity
 
     private String appId;//小程序appId
 
+    /**
+     * 账户余额扣减前
+     */
+    private BigDecimal accBalanceBefore;
+    /**
+     * 账户余额扣减后
+     */
+    private BigDecimal accBalanceAfter;
+
 }

+ 26 - 13
fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseVideoServiceImpl.java

@@ -4,6 +4,7 @@ import cn.hutool.json.JSONUtil;
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.Wrapper;
+import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.fs.common.BeanCopyUtils;
 import com.fs.common.core.domain.R;
@@ -65,6 +66,7 @@ import com.fs.system.mapper.SysDictDataMapper;
 import com.fs.system.service.ISysConfigService;
 import com.fs.voice.utils.StringUtil;
 import com.github.binarywang.wxpay.bean.transfer.TransferBillsResult;
+import com.google.common.collect.Sets;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.lang.exception.ExceptionUtils;
@@ -88,6 +90,7 @@ import java.time.Instant;
 import java.time.LocalDateTime;
 import java.time.ZoneId;
 import java.util.*;
+import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicLong;
 import java.util.stream.Collectors;
@@ -116,6 +119,7 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
      * 公司红包金额
      */
     private static final String REDPACKET_COMPANY_MONEY = "redpacket_money";
+    private static final String REDPACKET_COMPANY_MONEY_CHANGE = "redpacket_money_CHANGE";
 
     private static final String miniappRealLink = "/pages_course/video.html?course=";
     private static final String REAL_LINK_PREFIX = "/courseH5/pages/course/learning?course=";
@@ -1080,8 +1084,7 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
         packetParam.setAppId(param.getAppId());
         packetParam.setUser(user);
 
-        System.out.println("红包金额"+amount);
-        System.out.println("红包商户号"+packetParam);
+        logger.info("红包金额 {},红包商户号 {}",amount,packetParam);
         //2025.6.19 红包金额为0的时候
         if (amount.compareTo(BigDecimal.ZERO)>0){
 
@@ -1132,11 +1135,17 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
     }
 
     private R sendRedPacketRewardToUser(FsCourseSendRewardUParam param, FsCourseWatchLog log, CourseConfig config, WxSendRedPacketParam packetParam, BigDecimal amount) {
-        SysConfig sysConfig = sysConfigService.selectConfigByConfigKey("company.money");
-        String configValue = sysConfig.getConfigValue();
-        BigDecimal companyMoney = new BigDecimal(configValue);
+
+        BigDecimal companyMoney = redisCache.getCacheObject(REDPACKET_COMPANY_MONEY);
+        if(ObjectUtils.isNull(companyMoney)){
+            SysConfig sysConfig = sysConfigService.selectConfigByConfigKey("company.money");
+            String configValue = sysConfig.getConfigValue();
+            companyMoney = new BigDecimal(configValue);
+            logger.info("缓存公司余额为空,从数据库读取 companyMoney: {}",companyMoney);
+        }
+
         if (companyMoney.compareTo(BigDecimal.ZERO) <= 0) {
-            logger.info("润天账户余额: {} 不足!", configValue);
+            logger.info("润天账户余额: {} 不足!", companyMoney);
             return R.error("[红包领取] 账户余额不足,请联系管理员!");
         }
 
@@ -1164,18 +1173,22 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
             redPacketLog.setAmount(amount);
             redPacketLog.setWatchLogId(log.getLogId() != null ? log.getLogId() : null);
             redPacketLog.setPeriodId(param.getPeriodId());
-            redPacketLogMapper.insertFsCourseRedPacketLog(redPacketLog);
+            redPacketLog.setAccBalanceBefore(companyMoney);
+            redPacketLog.setAccBalanceAfter(companyMoney.subtract(amount));
 
-            // 更新观看记录的奖励类型
-            log.setRewardType(config.getRewardType());
-            courseWatchLogMapper.updateFsCourseWatchLog(log);
+            CompletableFuture.runAsync(() -> {
+                redPacketLogMapper.insertFsCourseRedPacketLog(redPacketLog);
+                // 更新观看记录的奖励类型
+                log.setRewardType(config.getRewardType());
+                courseWatchLogMapper.updateFsCourseWatchLog(log);
+            });
 
             // 更新账户余额
             logger.info("[更新账户余额] 当前余额{} 更新后余额{}",companyMoney.toPlainString(),companyMoney.subtract(amount).toPlainString());
-            companyMoney = companyMoney.subtract(amount);
-            sysConfig.setConfigValue(companyMoney.setScale(4,RoundingMode.HALF_UP).toPlainString());
-            sysConfigService.updateConfig(sysConfig);
+            redisCache.setCacheList(REDPACKET_COMPANY_MONEY_CHANGE, Arrays.asList(companyMoney,companyMoney.subtract(amount)));
 
+            companyMoney = companyMoney.subtract(amount);
+            redisCache.setCacheObject(REDPACKET_COMPANY_MONEY,companyMoney);
             return sendRedPacket;
         } else {
             return R.error("奖励发送失败,请联系客服");

+ 2 - 2
fs-service/src/main/java/com/fs/his/service/impl/FsStorePaymentServiceImpl.java

@@ -499,7 +499,7 @@ public class FsStorePaymentServiceImpl implements IFsStorePaymentService {
             String appId = StringUtils.isBlank(param.getAppId()) ? config.getMiniappId() : param.getAppId();
             config.setAppId(appId);
         }
-        System.out.println("最终传参"+config);
+        logger.info("最终传参 {}",config);
         //组合返回参数
         R result = new R();
         // 根据 isNew 判断使用哪种发红包方式
@@ -510,7 +510,7 @@ public class FsStorePaymentServiceImpl implements IFsStorePaymentService {
         }
         result.put("mchId",config.getMchId()+"");
         result.put("isNew",config.getIsNew());
-        System.out.println("红包返回:"+result);
+        logger.info("红包返回:{}",result);
         return result;
     }
 

+ 21 - 8
fs-service/src/main/java/com/fs/system/service/impl/SysConfigServiceImpl.java

@@ -14,6 +14,7 @@ import com.fs.system.service.ISysConfigService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import javax.annotation.PostConstruct;
+import javax.annotation.concurrent.ThreadSafe;
 import java.util.Collection;
 import java.util.List;
 
@@ -23,6 +24,7 @@ import java.util.List;
 
  */
 @Service
+@ThreadSafe
 public class SysConfigServiceImpl implements ISysConfigService
 {
     @Autowired
@@ -31,6 +33,8 @@ public class SysConfigServiceImpl implements ISysConfigService
     @Autowired
     private RedisCache redisCache;
 
+    private static final Object CONFIG_LOCK = new Object();
+
     /**
      * 项目启动时,初始化参数到缓存
      */
@@ -69,15 +73,24 @@ public class SysConfigServiceImpl implements ISysConfigService
         {
             return configValue;
         }
-        SysConfig config = new SysConfig();
-        config.setConfigKey(configKey);
-        SysConfig retConfig = configMapper.selectConfig(config);
-        if (StringUtils.isNotNull(retConfig))
-        {
-            redisCache.setCacheObject(getCacheKey(configKey), retConfig.getConfigValue());
-            return retConfig.getConfigValue();
+
+        synchronized (CONFIG_LOCK){
+            configValue = Convert.toStr(redisCache.getCacheObject(getCacheKey(configKey)));
+            if (StringUtils.isNotEmpty(configValue))
+            {
+                return configValue;
+            }
+
+            SysConfig config = new SysConfig();
+            config.setConfigKey(configKey);
+            SysConfig retConfig = configMapper.selectConfig(config);
+            if (StringUtils.isNotNull(retConfig))
+            {
+                redisCache.setCacheObject(getCacheKey(configKey), retConfig.getConfigValue());
+                return retConfig.getConfigValue();
+            }
+            return StringUtils.EMPTY;
         }
-        return StringUtils.EMPTY;
     }
 
     /**

+ 6 - 0
fs-service/src/main/resources/mapper/course/FsCourseRedPacketLogMapper.xml

@@ -110,6 +110,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="result != null">result,</if>
             <if test="batchId != null">batch_id,</if>
             <if test="appId != null">app_id,</if>
+            <if test="appId != null">app_id,</if>
+            <if test="appId != null">app_id,</if>
+            <if test="accBalanceBefore != null">acc_balance_before,</if>
+            <if test="accBalanceAfter != null">acc_balance_after,</if>
          </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="courseId != null">#{courseId},</if>
@@ -129,6 +133,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="result != null">#{result},</if>
             <if test="batchId != null">#{batchId},</if>
             <if test="appId != null">#{appId},</if>
+            <if test="accBalanceBefore != null">#{accBalanceBefore},</if>
+            <if test="accBalanceAfter != null">#{accBalanceAfter},</if>
         </trim>
     </insert>